-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>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164855 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 86e9dc2..bc25c0a 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -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.