diff options
-rw-r--r-- | clang/include/clang/Sema/ScopeInfo.h | 6 | ||||
-rw-r--r-- | clang/lib/Sema/ScopeInfo.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 18 | ||||
-rw-r--r-- | clang/test/SemaObjC/arc-repeated-weak.mm | 23 |
4 files changed, 76 insertions, 3 deletions
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 0592265ccdf..7fbe07dc942 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -25,6 +25,7 @@ namespace clang { class Decl; class BlockDecl; class CXXMethodDecl; +class ObjCPropertyDecl; class IdentifierInfo; class LabelDecl; class ReturnStmt; @@ -34,6 +35,7 @@ class VarDecl; class DeclRefExpr; class ObjCIvarRefExpr; class ObjCPropertyRefExpr; +class ObjCMessageExpr; namespace sema { @@ -166,6 +168,7 @@ public: public: WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); + WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); WeakObjectProfileTy(const DeclRefExpr *RE); WeakObjectProfileTy(const ObjCIvarRefExpr *RE); @@ -261,6 +264,9 @@ public: template <typename ExprT> inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); + void recordUseOfWeak(const ObjCMessageExpr *Msg, + const ObjCPropertyDecl *Prop); + /// Record that a given expression is a "safe" access of a weak object (e.g. /// assigning it to a strong variable.) /// diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 76f967d588b..c1d66299058 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -103,6 +103,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( } } +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE, + const ObjCPropertyDecl *Prop) + : Base(0, true), Property(Prop) { + if (BaseE) + Base = getBaseInfo(BaseE); + // else, this is a message accessing a property on super. +} + FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( const DeclRefExpr *DRE) : Base(0, true), Property(DRE->getDecl()) { @@ -114,6 +122,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { } +void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg, + const ObjCPropertyDecl *Prop) { + assert(Msg && Prop); + WeakUseVector &Uses = + WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)]; + Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0)); +} + void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { E = E->IgnoreParenCasts(); @@ -138,11 +154,21 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { // Has this weak object been seen before? FunctionScopeInfo::WeakObjectUseMap::iterator Uses; if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) - Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr)); + Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) - Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE)); + Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE)); + Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE)); + else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(MsgE)) { + Uses = WeakObjectUses.end(); + if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) { + if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) { + Uses = + WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(), + Prop)); + } + } + } else return; diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 1bb4df04836..3f9c14c6852 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -2434,6 +2434,24 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // In ARC, check for message sends which are likely to introduce // retain cycles. checkRetainCycles(Result); + + if (!isImplicit && Method) { + if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { + bool IsWeak = + Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; + if (!IsWeak && Sel.isUnarySelector()) + IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; + + if (IsWeak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + LBracLoc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result, Prop); + + } + } + } } return MaybeBindToTemporary(Result); diff --git a/clang/test/SemaObjC/arc-repeated-weak.mm b/clang/test/SemaObjC/arc-repeated-weak.mm index 1c6578ef131..ca13e20dcf2 100644 --- a/clang/test/SemaObjC/arc-repeated-weak.mm +++ b/clang/test/SemaObjC/arc-repeated-weak.mm @@ -99,6 +99,29 @@ void globals() { use(a); // expected-note{{also accessed here}} } +void messageGetter(Test *a) { + use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} + use([a weakProp]); // expected-note{{also accessed here}} +} + +void messageSetter(Test *a) { + [a setWeakProp:get()]; // no-warning + [a setWeakProp:get()]; // no-warning +} + +void messageSetterAndGetter(Test *a) { + [a setWeakProp:get()]; // expected-note{{also accessed here}} + use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} +} + +void mixDotAndMessageSend(Test *a, Test *b) { + use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} + use([a weakProp]); // expected-note{{also accessed here}} + + use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} + use(b.weakProp); // expected-note{{also accessed here}} +} + void assignToStrongWrongInit(Test *a) { id val = a.weakProp; // expected-note{{also accessed here}} |