[cfe-commits] r165718 - in /cfe/trunk: include/clang/Sema/ScopeInfo.h lib/Sema/ScopeInfo.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/arc-repeated-weak.mm

Jordan Rose jordan_rose at apple.com
Thu Oct 11 09:06:21 PDT 2012


Author: jrose
Date: Thu Oct 11 11:06:21 2012
New Revision: 165718

URL: http://llvm.org/viewvc/llvm-project?rev=165718&view=rev
Log:
-Warc-repeated-use-of-weak: Check messages to property accessors as well.

Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.

This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.

<rdar://problem/12407765>

Modified:
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/lib/Sema/ScopeInfo.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/arc-repeated-weak.mm

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=165718&r1=165717&r2=165718&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Thu Oct 11 11:06:21 2012
@@ -25,6 +25,7 @@
 class Decl;
 class BlockDecl;
 class CXXMethodDecl;
+class ObjCPropertyDecl;
 class IdentifierInfo;
 class LabelDecl;
 class ReturnStmt;
@@ -34,6 +35,7 @@
 class DeclRefExpr;
 class ObjCIvarRefExpr;
 class ObjCPropertyRefExpr;
+class ObjCMessageExpr;
 
 namespace sema {
 
@@ -166,6 +168,7 @@
 
   public:
     WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+    WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
     WeakObjectProfileTy(const DeclRefExpr *RE);
     WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
 
@@ -261,6 +264,9 @@
   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.)
   ///

Modified: cfe/trunk/lib/Sema/ScopeInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=165718&r1=165717&r2=165718&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/ScopeInfo.cpp (original)
+++ cfe/trunk/lib/Sema/ScopeInfo.cpp Thu Oct 11 11:06:21 2012
@@ -103,6 +103,14 @@
   }
 }
 
+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 @@
   : 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 @@
   // 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;
 

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=165718&r1=165717&r2=165718&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu Oct 11 11:06:21 2012
@@ -2434,6 +2434,24 @@
     // 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);

Modified: cfe/trunk/test/SemaObjC/arc-repeated-weak.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-repeated-weak.mm?rev=165718&r1=165717&r2=165718&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-repeated-weak.mm (original)
+++ cfe/trunk/test/SemaObjC/arc-repeated-weak.mm Thu Oct 11 11:06:21 2012
@@ -99,6 +99,29 @@
   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}}





More information about the cfe-commits mailing list