[cfe-commits] r172134 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp test/Analysis/objc_invalidation.m

Anna Zaks ganna at apple.com
Thu Jan 10 14:44:16 PST 2013


Author: zaks
Date: Thu Jan 10 16:44:16 2013
New Revision: 172134

URL: http://llvm.org/viewvc/llvm-project?rev=172134&view=rev
Log:
[analyzer] Fix non-determinizm introduced in r172104.

In some cases, we just pick any ivar that needs invalidation and attach
the warning to it. Picking the first from DenseMap of pointer keys was
triggering non-deterministic output.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
    cfe/trunk/test/Analysis/objc_invalidation.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp?rev=172134&r1=172133&r2=172134&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp Thu Jan 10 16:44:16 2013
@@ -175,7 +175,8 @@
 
   /// Check if ivar should be tracked and add to TrackedIvars if positive.
   /// Returns true if ivar should be tracked.
-  static bool trackIvar(const ObjCIvarDecl *Iv, IvarSet &TrackedIvars);
+  static bool trackIvar(const ObjCIvarDecl *Iv, IvarSet &TrackedIvars,
+                        const ObjCIvarDecl **FirstIvarDecl);
 
   /// Given the property declaration, and the list of tracked ivars, finds
   /// the ivar backing the property when possible. Returns '0' when no such
@@ -183,7 +184,8 @@
   static const ObjCIvarDecl *findPropertyBackingIvar(
       const ObjCPropertyDecl *Prop,
       const ObjCInterfaceDecl *InterfaceD,
-      IvarSet &TrackedIvars);
+      IvarSet &TrackedIvars,
+      const ObjCIvarDecl **FirstIvarDecl);
 
   /// Print ivar name or the property if the given ivar backs a property.
   static void printIvar(llvm::raw_svector_ostream &os,
@@ -251,7 +253,8 @@
 }
 
 bool IvarInvalidationChecker::trackIvar(const ObjCIvarDecl *Iv,
-                                        IvarSet &TrackedIvars) {
+                                        IvarSet &TrackedIvars,
+                                        const ObjCIvarDecl **FirstIvarDecl) {
   QualType IvQTy = Iv->getType();
   const ObjCObjectPointerType *IvTy = IvQTy->getAs<ObjCObjectPointerType>();
   if (!IvTy)
@@ -261,7 +264,10 @@
   InvalidationInfo Info;
   containsInvalidationMethod(IvInterf, Info);
   if (Info.needsInvalidation()) {
-    TrackedIvars[cast<ObjCIvarDecl>(Iv->getCanonicalDecl())] = Info;
+    const ObjCIvarDecl *I = cast<ObjCIvarDecl>(Iv->getCanonicalDecl());
+    TrackedIvars[I] = Info;
+    if (!*FirstIvarDecl)
+      *FirstIvarDecl = I;
     return true;
   }
   return false;
@@ -270,7 +276,8 @@
 const ObjCIvarDecl *IvarInvalidationChecker::findPropertyBackingIvar(
                         const ObjCPropertyDecl *Prop,
                         const ObjCInterfaceDecl *InterfaceD,
-                        IvarSet &TrackedIvars) {
+                        IvarSet &TrackedIvars,
+                        const ObjCIvarDecl **FirstIvarDecl) {
   const ObjCIvarDecl *IvarD = 0;
 
   // Lookup for the synthesized case.
@@ -282,7 +289,7 @@
       return IvarD;
     }
     // If the ivar is synthesized we still want to track it.
-    if (trackIvar(IvarD, TrackedIvars))
+    if (trackIvar(IvarD, TrackedIvars, FirstIvarDecl))
       return IvarD;
   }
 
@@ -330,13 +337,17 @@
                                           BugReporter &BR) const {
   // Collect all ivars that need cleanup.
   IvarSet Ivars;
+  // Record the first Ivar needing invalidation; used in reporting when only
+  // one ivar is sufficient. Cannot grab the first on the Ivars set to ensure
+  // deterministic output.
+  const ObjCIvarDecl *FirstIvarDecl = 0;
   const ObjCInterfaceDecl *InterfaceD = ImplD->getClassInterface();
 
   // Collect ivars declared in this class, its extensions and its implementation
   ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(InterfaceD);
   for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
        Iv= Iv->getNextIvar())
-    trackIvar(Iv, Ivars);
+    trackIvar(Iv, Ivars, &FirstIvarDecl);
 
   // Construct Property/Property Accessor to Ivar maps to assist checking if an
   // ivar which is backing a property has been reset.
@@ -352,7 +363,8 @@
       I = PropMap.begin(), E = PropMap.end(); I != E; ++I) {
     const ObjCPropertyDecl *PD = I->second;
 
-    const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterfaceD, Ivars);
+    const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterfaceD, Ivars,
+                                                     &FirstIvarDecl);
     if (!ID) {
       continue;
     }
@@ -390,14 +402,14 @@
     llvm::raw_svector_ostream os(sbuf);
     os << "No invalidation method declared in the @interface for "
        << InterfaceD->getName() << "; ";
-    const ObjCIvarDecl *IvarDecl = Ivars.begin()->first;
-    printIvar(os, IvarDecl, IvarToPopertyMap);
+    assert(FirstIvarDecl);
+    printIvar(os, FirstIvarDecl, IvarToPopertyMap);
     os << "needs to be invalidated";
 
     PathDiagnosticLocation IvarDecLocation =
-        PathDiagnosticLocation::createBegin(IvarDecl, BR.getSourceManager());
+      PathDiagnosticLocation::createBegin(FirstIvarDecl, BR.getSourceManager());
 
-    BR.EmitBasicReport(IvarDecl, "Incomplete invalidation",
+    BR.EmitBasicReport(FirstIvarDecl, "Incomplete invalidation",
                        categories::CoreFoundationObjectiveC, os.str(),
                        IvarDecLocation);
     return;
@@ -455,14 +467,14 @@
     llvm::raw_svector_ostream os(sbuf);
     os << "No invalidation method defined in the @implementation for "
        << InterfaceD->getName() << "; ";
-    const ObjCIvarDecl *IvarDecl = Ivars.begin()->first;
-    printIvar(os, IvarDecl, IvarToPopertyMap);
+    assert(FirstIvarDecl);
+    printIvar(os, FirstIvarDecl, IvarToPopertyMap);
     os << "needs to be invalidated";
 
     PathDiagnosticLocation IvarDecLocation =
-        PathDiagnosticLocation::createBegin(IvarDecl,
+        PathDiagnosticLocation::createBegin(FirstIvarDecl,
                                             BR.getSourceManager());
-    BR.EmitBasicReport(IvarDecl, "Incomplete invalidation",
+    BR.EmitBasicReport(FirstIvarDecl, "Incomplete invalidation",
                        categories::CoreFoundationObjectiveC, os.str(),
                        IvarDecLocation);
   }
@@ -576,7 +588,7 @@
 }
 
 void IvarInvalidationChecker::MethodCrawler::VisitObjCMessageExpr(
-    const ObjCMessageExpr *ME) {
+  const ObjCMessageExpr *ME) {
   const ObjCMethodDecl *MD = ME->getMethodDecl();
   const Expr *Receiver = ME->getInstanceReceiver();
 

Modified: cfe/trunk/test/Analysis/objc_invalidation.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/objc_invalidation.m?rev=172134&r1=172133&r2=172134&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/objc_invalidation.m (original)
+++ cfe/trunk/test/Analysis/objc_invalidation.m Thu Jan 10 16:44:16 2013
@@ -214,9 +214,9 @@
 
 @interface MissingInvalidationMethodDecl2 : NSObject {
 @private
-    Foo *_foo1;
+    Foo *_foo1; // expected-warning {{No invalidation method declared in the @interface for MissingInvalidationMethodDecl2; Instance variable _foo1 needs to be invalidated}} 
 }
- at property (strong) Foo *bar1; // expected-warning {{No invalidation method declared in the @interface for MissingInvalidationMethodDecl2; Property bar1 needs to be invalidated}} 
+ at property (strong) Foo *bar1; 
 @end
 @implementation MissingInvalidationMethodDecl2
 @end





More information about the cfe-commits mailing list