[cfe-commits] r164855 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/ScopeInfo.h lib/Sema/AnalysisBasedWarnings.cpp lib/Sema/Sema.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprMember.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-repeated-weak.mm

Jordan Rose jordan_rose at apple.com
Fri Sep 28 15:21:35 PDT 2012


Author: jrose
Date: Fri Sep 28 17:21:35 2012
New Revision: 164855

URL: http://llvm.org/viewvc/llvm-project?rev=164855&view=rev
Log:
-Warc-repeated-use-of-weak: check ivars and variables as well.

Like properties, loading from a weak ivar twice in the same function can
give you inconsistent results if the object is deallocated between the
two loads. It is safer to assign to a strong local variable and use that.

Second half of <rdar://problem/12280249>.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprMember.cpp
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
    cfe/trunk/test/SemaObjC/arc-repeated-weak.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 28 17:21:35 2012
@@ -710,14 +710,16 @@
   "unpredictably null in ARC mode">,
   InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore;
 def warn_arc_repeated_use_of_weak : Warning <
-  "weak property is accessed multiple times in this "
-  "%select{function|method|block|lambda}0 but may be unpredictably set to nil; "
-  "assign to a strong variable to keep the object alive">,
+  "weak %select{variable|property|implicit property|instance variable}0 %1 is "
+  "accessed multiple times in this %select{function|method|block|lambda}2 "
+  "but may be unpredictably set to nil; assign to a strong variable to keep "
+  "the object alive">,
   InGroup<ARCRepeatedUseOfWeak>, DefaultIgnore;
 def warn_arc_possible_repeated_use_of_weak : Warning <
-  "weak property may be accessed multiple times in this "
-  "%select{function|method|block|lambda}0 but may be unpredictably set to nil; "
-  "assign to a strong variable to keep the object alive">,
+  "weak %select{variable|property|implicit property|instance variable}0 %1 may "
+  "be accessed multiple times in this %select{function|method|block|lambda}2 "
+  "and may be unpredictably set to nil; assign to a strong variable to keep "
+  "the object alive">,
   InGroup<ARCRepeatedUseOfWeakMaybe>, DefaultIgnore;
 def note_arc_weak_also_accessed_here : Note<
   "also accessed here">;

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Fri Sep 28 17:21:35 2012
@@ -30,6 +30,8 @@
 class Scope;
 class SwitchStmt;
 class VarDecl;
+class DeclRefExpr;
+class ObjCIvarRefExpr;
 class ObjCPropertyRefExpr;
 
 namespace sema {
@@ -132,6 +134,8 @@
   /// [self foo].prop   | 0 (unknown)         | prop (ObjCPropertyDecl)
   /// self.prop1.prop2  | prop1 (ObjCPropertyDecl)    | prop2 (ObjCPropertyDecl)
   /// MyClass.prop      | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
+  /// weakVar           | 0 (known)           | weakVar (VarDecl)
+  /// self->weakIvar    | self (VarDecl)      | weakIvar (ObjCIvarDecl)
   ///
   /// Objects are identified with only two Decls to make it reasonably fast to
   /// compare them.
@@ -151,6 +155,9 @@
     /// case of "implicit" properties (regular methods accessed via dot syntax).
     const NamedDecl *Property;
 
+    /// Used to find the proper base profile for a given base expression.
+    static BaseInfoTy getBaseInfo(const Expr *BaseE);
+
     // For use in DenseMap.
     friend struct llvm::DenseMapInfo<WeakObjectProfileTy>;
     inline WeakObjectProfileTy();
@@ -158,6 +165,8 @@
 
   public:
     WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+    WeakObjectProfileTy(const DeclRefExpr *RE);
+    WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
 
     const NamedDecl *getProperty() const { return Property; }
 
@@ -219,10 +228,11 @@
   WeakObjectUseMap WeakObjectUses;
 
 public:
-  /// Record that a weak property was accessed.
+  /// Record that a weak object was accessed.
   ///
   /// Part of the implementation of -Wrepeated-use-of-weak.
-  void recordUseOfWeak(const ObjCPropertyRefExpr *PropE);
+  template <typename ExprT>
+  inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
 
   /// Record that a given expression is a "safe" access of a weak object (e.g.
   /// assigning it to a strong variable.)
@@ -518,8 +528,15 @@
   return Result;
 }
 
+template <typename ExprT>
+void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
+  assert(E);
+  WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
+  Uses.push_back(WeakUseTy(E, IsRead));
 }
-}
+
+} // end namespace sema
+} // end namespace clang
 
 namespace llvm {
   template <>

Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Fri Sep 28 17:21:35 2012
@@ -957,19 +957,42 @@
     const WeakObjectProfileTy &Key = I->second->first;
     const WeakUseVector &Uses = I->second->second;
 
-    // For complicated expressions like self.foo.bar, it's hard to keep track
-    // of whether 'self.foo' is the same between two cases. We can only be
-    // 100% sure of a repeated use if the "base" part of the key is a variable,
-    // rather than, say, another property.
+    // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
+    // may not contain enough information to determine that these are different
+    // properties. We can only be 100% sure of a repeated use in certain cases,
+    // and we adjust the diagnostic kind accordingly so that the less certain
+    // case can be turned off if it is too noisy.
     unsigned DiagKind;
     if (Key.isExactProfile())
       DiagKind = diag::warn_arc_repeated_use_of_weak;
     else
       DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
 
+    // Classify the weak object being accessed for better warning text.
+    // This enum should stay in sync with the cases in
+    // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
+    enum {
+      Variable,
+      Property,
+      ImplicitProperty,
+      Ivar
+    } ObjectKind;
+
+    const NamedDecl *D = Key.getProperty();
+    if (isa<VarDecl>(D))
+      ObjectKind = Variable;
+    else if (isa<ObjCPropertyDecl>(D))
+      ObjectKind = Property;
+    else if (isa<ObjCMethodDecl>(D))
+      ObjectKind = ImplicitProperty;
+    else if (isa<ObjCIvarDecl>(D))
+      ObjectKind = Ivar;
+    else
+      llvm_unreachable("Unexpected weak object kind!");
+
     // Show the first time the object was read.
     S.Diag(FirstRead->getLocStart(), DiagKind)
-      << FunctionKind
+      << ObjectKind << D << FunctionKind
       << FirstRead->getSourceRange();
 
     // Print all the other accesses as notes.

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Sep 28 17:21:35 2012
@@ -82,65 +82,77 @@
   return M->getSelfDecl() == Param;
 }
 
+FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
+FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
+  E = E->IgnoreParenCasts();
+
+  const NamedDecl *D = 0;
+  bool IsExact = false;
+
+  switch (E->getStmtClass()) {
+  case Stmt::DeclRefExprClass:
+    D = cast<DeclRefExpr>(E)->getDecl();
+    IsExact = isa<VarDecl>(D);
+    break;
+  case Stmt::MemberExprClass: {
+    const MemberExpr *ME = cast<MemberExpr>(E);
+    D = ME->getMemberDecl();
+    IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
+    break;
+  }
+  case Stmt::ObjCIvarRefExprClass: {
+    const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
+    D = IE->getDecl();
+    IsExact = isSelfExpr(IE->getBase());
+    break;
+  }
+  case Stmt::PseudoObjectExprClass: {
+    const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
+    const ObjCPropertyRefExpr *BaseProp =
+      dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
+    if (BaseProp) {
+      D = getBestPropertyDecl(BaseProp);
+
+      const Expr *DoubleBase = BaseProp->getBase();
+      if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
+        DoubleBase = OVE->getSourceExpr();
+
+      IsExact = isSelfExpr(DoubleBase);
+    }
+    break;
+  }
+  default:
+    break;
+  }
+
+  return BaseInfoTy(D, IsExact);
+}
+
+
 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
                                           const ObjCPropertyRefExpr *PropE)
-    : Base(0, false), Property(getBestPropertyDecl(PropE)) {
+    : Base(0, true), Property(getBestPropertyDecl(PropE)) {
 
   if (PropE->isObjectReceiver()) {
     const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
-    const Expr *E = OVE->getSourceExpr()->IgnoreParenCasts();
-
-    switch (E->getStmtClass()) {
-    case Stmt::DeclRefExprClass:
-      Base.setPointer(cast<DeclRefExpr>(E)->getDecl());
-      Base.setInt(isa<VarDecl>(Base.getPointer()));
-      break;
-    case Stmt::MemberExprClass: {
-      const MemberExpr *ME = cast<MemberExpr>(E);
-      Base.setPointer(ME->getMemberDecl());
-      Base.setInt(isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()));
-      break;
-    }
-    case Stmt::ObjCIvarRefExprClass: {
-      const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
-      Base.setPointer(IE->getDecl());
-      if (isSelfExpr(IE->getBase()))
-        Base.setInt(true);
-      break;
-    }
-    case Stmt::PseudoObjectExprClass: {
-      const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
-      const ObjCPropertyRefExpr *BaseProp =
-        dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
-      if (BaseProp) {
-        Base.setPointer(getBestPropertyDecl(BaseProp));
-
-        const Expr *DoubleBase = BaseProp->getBase();
-        if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
-          DoubleBase = OVE->getSourceExpr();
-
-        if (isSelfExpr(DoubleBase))
-          Base.setInt(true);
-      }
-      break;
-    }
-    default:
-      break;
-    }
+    const Expr *E = OVE->getSourceExpr();
+    Base = getBaseInfo(E);
   } else if (PropE->isClassReceiver()) {
     Base.setPointer(PropE->getClassReceiver());
-    Base.setInt(true);
   } else {
     assert(PropE->isSuperReceiver());
-    Base.setInt(true);
   }
 }
 
-void FunctionScopeInfo::recordUseOfWeak(const ObjCPropertyRefExpr *RefExpr) {
-  assert(RefExpr);
-  WeakUseVector &Uses =
-    WeakObjectUses[FunctionScopeInfo::WeakObjectProfileTy(RefExpr)];
-  Uses.push_back(WeakUseTy(RefExpr, RefExpr->isMessagingGetter()));
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
+                                                      const DeclRefExpr *DRE)
+  : Base(0, true), Property(DRE->getDecl()) {
+  assert(isa<VarDecl>(Property));
+}
+
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
+                                                  const ObjCIvarRefExpr *IvarE)
+  : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
 }
 
 void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
@@ -164,22 +176,27 @@
     return;
   }
 
-  if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
-    // Has this property been seen as a weak property?
-    FunctionScopeInfo::WeakObjectUseMap::iterator Uses =
-      WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr));
-    if (Uses == WeakObjectUses.end())
-      return;
+  // 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));
+  else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
+    Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE));
+  else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+    Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE));
+  else
+    return;
 
-    // Has there been a read from the property using this Expr?
-    FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
-      std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
-    if (ThisUse == Uses->second.rend())
-      return;
+  if (Uses == WeakObjectUses.end())
+    return;
 
-    ThisUse->markSafe();
+  // Has there been a read from the object using this Expr?
+  FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
+    std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
+  if (ThisUse == Uses->second.rend())
     return;
-  }
+
+  ThisUse->markSafe();
 }
 
 BlockScopeInfo::~BlockScopeInfo() { }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Sep 28 17:21:35 2012
@@ -5639,9 +5639,19 @@
   
   if (LHSType.isNull())
     LHSType = LHS->getType();
+
+  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+
+  if (LT == Qualifiers::OCL_Weak) {
+    DiagnosticsEngine::Level Level =
+      Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
+    if (Level != DiagnosticsEngine::Ignored)
+      getCurFunction()->markSafeWeakUse(LHS);
+  }
+
   if (checkUnsafeAssigns(Loc, LHSType, RHS))
     return;
-  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+
   // FIXME. Check for other life times.
   if (LT != Qualifiers::OCL_None)
     return;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Sep 28 17:21:35 2012
@@ -1425,6 +1425,15 @@
 
   MarkDeclRefReferenced(E);
 
+  if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
+      Ty.getObjCLifetime() == Qualifiers::OCL_Weak) {
+    DiagnosticsEngine::Level Level =
+      Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
+                               E->getLocStart());
+    if (Level != DiagnosticsEngine::Ignored)
+      getCurFunction()->recordUseOfWeak(E);
+  }
+
   // Just in case we're building an illegal pointer-to-member.
   FieldDecl *FD = dyn_cast<FieldDecl>(D);
   if (FD && FD->isBitField())
@@ -1986,9 +1995,22 @@
       ObjCMethodFamily MF = CurMethod->getMethodFamily();
       if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize)
         Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
-      return Owned(new (Context)
-                   ObjCIvarRefExpr(IV, IV->getType(), Loc,
-                                   SelfExpr.take(), true, true));
+
+      ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+                                                              Loc,
+                                                              SelfExpr.take(),
+                                                              true, true);
+
+      if (getLangOpts().ObjCAutoRefCount) {
+        if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+          DiagnosticsEngine::Level Level =
+            Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
+          if (Level != DiagnosticsEngine::Ignored)
+            getCurFunction()->recordUseOfWeak(Result);
+        }
+      }
+      
+      return Owned(Result);
     }
   } else if (CurMethod->isInstanceMethod()) {
     // We should warn if a local variable hides an ivar.

Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Fri Sep 28 17:21:35 2012
@@ -13,6 +13,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
@@ -1272,9 +1273,23 @@
       if (warn)
         Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
     }
-    return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
-                                               MemberLoc, BaseExpr.take(),
-                                               IsArrow));
+
+    ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+                                                            MemberLoc,
+                                                            BaseExpr.take(),
+                                                            IsArrow);
+
+    if (getLangOpts().ObjCAutoRefCount) {
+      if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+        DiagnosticsEngine::Level Level =
+          Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
+                                   MemberLoc);
+        if (Level != DiagnosticsEngine::Ignored)
+          getCurFunction()->recordUseOfWeak(Result);
+      }
+    }
+
+    return Owned(Result);
   }
 
   // Objective-C property access.

Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Fri Sep 28 17:21:35 2012
@@ -845,7 +845,8 @@
       S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
                                  SyntacticForm->getLocStart());
     if (Level != DiagnosticsEngine::Ignored)
-      S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr);
+      S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
+                                         SyntacticRefExpr->isMessagingGetter());
   }
 
   return PseudoOpBuilder::complete(SyntacticForm);

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=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-repeated-weak.mm (original)
+++ cfe/trunk/test/SemaObjC/arc-repeated-weak.mm Fri Sep 28 17:21:35 2012
@@ -3,6 +3,7 @@
 @interface Test {
 @public
   Test *ivar;
+  __weak id weakIvar;
 }
 @property(weak) Test *weakProp;
 @property(strong) Test *strongProp;
@@ -18,7 +19,7 @@
 #define nil ((id)0)
 
 void sanity(Test *a) {
-  use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
   use(a.weakProp); // expected-note{{also accessed here}}
 
   use(a.strongProp);
@@ -38,11 +39,22 @@
   id next = get();
   if (next)
     a.weakProp = next; // no-warning
+
+  a->weakIvar = get(); // no-warning
+  next = get();
+  if (next)
+    a->weakIvar = next; // no-warning
+
+  extern __weak id x;
+  x = get(); // no-warning
+  next = get();
+  if (next)
+    x = next; // no-warning
 }
 
 void assignThenRead(Test *a) {
   a.weakProp = get(); // expected-note{{also accessed here}}
-  use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
 }
 
 void twoVariables(Test *a, Test *b) {
@@ -51,22 +63,22 @@
 }
 
 void doubleLevelAccess(Test *a) {
-  use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+  use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times in this function and may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
 }
 
 void doubleLevelAccessIvar(Test *a) {
-  use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+  use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
 }
 
 void implicitProperties(Test *a) {
-  use(a.implicitProp); // expected-warning{{weak property is accessed multiple times}}
+  use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
   use(a.implicitProp); // expected-note{{also accessed here}}
 }
 
 void classProperties() {
-  use(Test.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
   use(Test.weakProp); // expected-note{{also accessed here}}
 }
 
@@ -76,16 +88,38 @@
   use(a.strongProp.weakProp); // no-warning
 }
 
+void ivars(Test *a) {
+  use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+  use(a->weakIvar); // expected-note{{also accessed here}}
+}
+
+void globals() {
+  extern __weak id a;
+  use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
+  use(a); // expected-note{{also accessed here}}
+}
+
 
 void assignToStrongWrongInit(Test *a) {
   id val = a.weakProp; // expected-note{{also accessed here}}
-  use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
 }
 
 void assignToStrongWrong(Test *a) {
   id val;
   val = a.weakProp; // expected-note{{also accessed here}}
-  use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+}
+
+void assignToIvarWrong(Test *a) {
+  a->weakIvar = get(); // expected-note{{also accessed here}}
+  use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+}
+
+void assignToGlobalWrong() {
+  extern __weak id a;
+  a = get(); // expected-note{{also accessed here}}
+  use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
 }
 
 void assignToStrongOK(Test *a) {
@@ -108,7 +142,7 @@
   use(a.weakProp); // no-warning
 
   use(^{
-    use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this block}}
+    use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
     use(a.weakProp); // expected-note{{also accessed here}}
   });
 }
@@ -119,16 +153,24 @@
 
 @implementation Test (Methods)
 - (void)sanity {
-  use(self.weakProp); // expected-warning{{weak property is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+  use(self.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
   use(self.weakProp); // expected-note{{also accessed here}}
 }
 
+- (void)ivars {
+  use(weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+  use(weakIvar); // expected-note{{also accessed here}}
+}
+
 - (void)doubleLevelAccessForSelf {
-  use(self.strongProp.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
   use(self.strongProp.weakProp); // expected-note{{also accessed here}}
 
-  use(self->ivar.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
   use(self->ivar.weakProp); // expected-note{{also accessed here}}
+
+  use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+  use(self->ivar->weakIvar); // expected-note{{also accessed here}}
 }
 
 - (void)distinctFromOther:(Test *)other {
@@ -137,6 +179,9 @@
 
   use(self->ivar.weakProp); // no-warning
   use(other->ivar.weakProp); // no-warning
+
+  use(self.strongProp->weakIvar); // no-warning
+  use(other.strongProp->weakIvar); // no-warning
 }
 @end
 
@@ -146,7 +191,7 @@
 
 public:
   void fields() {
-    use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+    use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
     use(a.weakProp); // expected-note{{also accessed here}}
   }
 
@@ -157,7 +202,7 @@
   }
 
   static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
-    use(x.a.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+    use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
     use(y.a.weakProp); // expected-note{{also accessed here}}
   }
 };
@@ -170,7 +215,7 @@
 // Most of these would require flow-sensitive analysis to silence correctly.
 
 void assignAfterRead(Test *a) {
-  if (!a.weakProp) // expected-warning{{weak property is accessed multiple times}}
+  if (!a.weakProp) // expected-warning{{weak property 'weakProp' is accessed multiple times}}
     a.weakProp = get(); // expected-note{{also accessed here}}
 }
 
@@ -178,25 +223,25 @@
   if (condition())
     a.weakProp = nil; // expected-note{{also accessed here}}
 
-  use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
 }
 
 void branch(Test *a) {
   if (condition())
-    use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+    use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
   else
     use(a.weakProp); // expected-note{{also accessed here}}
 }
 
 void doubleLevelAccess(Test *a, Test *b) {
-  use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+  use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
   use(b.strongProp.weakProp); // expected-note{{also accessed here}}
 
   use(a.weakProp.weakProp); // no-warning
 }
 
 void doubleLevelAccessIvar(Test *a, Test *b) {
-  use(a->ivar.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+  use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
   use(b->ivar.weakProp); // expected-note{{also accessed here}}
 
   use(a.strongProp.weakProp); // no-warning





More information about the cfe-commits mailing list