[cfe-commits] r153309 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/CheckerManager.h include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp lib/StaticAnalyzer/Core/CheckerManager.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp test/Analysis/retain-release-inline.m test/Analysis/retain-release.mm

Ted Kremenek kremenek at apple.com
Thu Mar 22 23:26:57 PDT 2012


Author: kremenek
Date: Fri Mar 23 01:26:56 2012
New Revision: 153309

URL: http://llvm.org/viewvc/llvm-project?rev=153309&view=rev
Log:
Avoid applying retain/release effects twice in RetainCountChecker when a function call was inlined (i.e., we do not need to apply summaries in such cases).

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/test/Analysis/retain-release-inline.m
    cfe/trunk/test/Analysis/retain-release.mm

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Fri Mar 23 01:26:56 2012
@@ -193,14 +193,16 @@
   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
                               const ExplodedNodeSet &Src,
                               const Stmt *S,
-                              ExprEngine &Eng) {
-    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
+                              ExprEngine &Eng,
+                              bool wasInlined = false) {
+    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
   }
 
   /// \brief Run checkers for visiting Stmts.
   void runCheckersForStmt(bool isPreVisit,
                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
-                          const Stmt *S, ExprEngine &Eng);
+                          const Stmt *S, ExprEngine &Eng,
+                          bool wasInlined = false);
 
   /// \brief Run checkers for pre-visiting obj-c messages.
   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h Fri Mar 23 01:26:56 2012
@@ -33,15 +33,21 @@
   NodeBuilder &NB;
 
 public:
+  /// If we are post visiting a call, this flag will be set if the
+  /// call was inlined.  In all other cases it will be false.
+  const bool wasInlined;
+  
   CheckerContext(NodeBuilder &builder,
                  ExprEngine &eng,
                  ExplodedNode *pred,
-                 const ProgramPoint &loc)
+                 const ProgramPoint &loc,
+                 bool wasInlined = false)
     : Eng(eng),
       Pred(pred),
       Changed(false),
       Location(loc),
-      NB(builder) {
+      NB(builder),
+      wasInlined(wasInlined) {
     assert(Pred->getState() &&
            "We should not call the checkers on an empty state.");
   }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Fri Mar 23 01:26:56 2012
@@ -2599,6 +2599,9 @@
 
 void RetainCountChecker::checkPostStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
+  if (C.wasInlined)
+    return;
+  
   // Get the callee.
   ProgramStateRef state = C.getState();
   const Expr *Callee = CE->getCallee();

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Fri Mar 23 01:26:56 2012
@@ -138,13 +138,15 @@
     const CheckersTy &Checkers;
     const Stmt *S;
     ExprEngine &Eng;
+    bool wasInlined;
 
     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
 
     CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
-                     const Stmt *s, ExprEngine &eng)
-      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
+                     const Stmt *s, ExprEngine &eng, bool wasInlined = false)
+      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
+        wasInlined(wasInlined) {}
 
     void runChecker(CheckerManager::CheckStmtFunc checkFn,
                     NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -153,8 +155,7 @@
                                            ProgramPoint::PostStmtKind;
       const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
                                 Pred->getLocationContext(), checkFn.Checker);
-      CheckerContext C(Bldr, Eng, Pred, L);
-
+      CheckerContext C(Bldr, Eng, Pred, L, wasInlined);
       checkFn(S, C);
     }
   };
@@ -165,9 +166,10 @@
                                         ExplodedNodeSet &Dst,
                                         const ExplodedNodeSet &Src,
                                         const Stmt *S,
-                                        ExprEngine &Eng) {
+                                        ExprEngine &Eng,
+                                        bool wasInlined) {
   CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
-                     S, Eng);
+                     S, Eng, wasInlined);
   expandGraphWithCheckers(C, Dst, Src);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Mar 23 01:26:56 2012
@@ -107,7 +107,8 @@
                                                     &Ctx);
   SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
   
-  getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this);
+  getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this,
+                                             /* wasInlined */ true);
   
   // Enqueue the next element in the block.
   for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) {

Modified: cfe/trunk/test/Analysis/retain-release-inline.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-inline.m?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-inline.m (original)
+++ cfe/trunk/test/Analysis/retain-release-inline.m Fri Mar 23 01:26:56 2012
@@ -314,3 +314,34 @@
   [x retain];
   [x release];
 }
+
+//===----------------------------------------------------------------------===//
+// Test not applying "double effects" from inlining and RetainCountChecker summaries.
+// If we inline a call, we should already see its retain/release semantics.
+//===----------------------------------------------------------------------===//
+
+__attribute__((cf_returns_retained)) CFStringRef test_return_inline(CFStringRef x) {
+  CFRetain(x);
+  return x;
+}
+
+void test_test_return_inline(char *bytes) {
+  CFStringRef str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0);
+  // After this call, 'str' really has +2 reference count.
+  CFStringRef str2 = test_return_inline(str);
+  // After this call, 'str' really has a +1 reference count.
+  CFRelease(str);
+  // After this call, 'str2' and 'str' has a +0 reference count.
+  CFRelease(str2);
+}
+
+void test_test_return_inline_2(char *bytes) {
+  CFStringRef str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // expected-warning {{leak}}
+  // After this call, 'str' really has +2 reference count.
+  CFStringRef str2 = test_return_inline(str);
+  // After this call, 'str' really has a +1 reference count.
+  CFRelease(str);
+}
+
+
+

Modified: cfe/trunk/test/Analysis/retain-release.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.mm?rev=153309&r1=153308&r2=153309&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.mm (original)
+++ cfe/trunk/test/Analysis/retain-release.mm Fri Mar 23 01:26:56 2012
@@ -341,9 +341,9 @@
 }
 int rdar10553686_positive(void)
 {
-  NSObject* bar = static_objc_cast<NSObject*>([[NSObject alloc] init]); // expected-warning {{Potential leak}}
+  NSObject* bar = static_objc_cast<NSObject*>([[NSObject alloc] init]);
   [bar release];
-  [bar retain];
+  [bar retain]; // expected-warning {{used after it is released}}
   return 0;
 }
 





More information about the cfe-commits mailing list