r210960 - Fix a crash in Retain Count checker error reporting

Anna Zaks ganna at apple.com
Fri Jun 13 16:47:38 PDT 2014


Author: zaks
Date: Fri Jun 13 18:47:38 2014
New Revision: 210960

URL: http://llvm.org/viewvc/llvm-project?rev=210960&view=rev
Log:
Fix a crash in Retain Count checker error reporting

Fixes a crash in Retain Count checker error reporting logic by handing
the allocation statement retrieval from a BlockEdge program point.

Also added a simple CFG dump routine for debugging.

Added:
    cfe/trunk/test/Analysis/objc-radar17039661.m
Modified:
    cfe/trunk/include/clang/Analysis/CFG.h
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp

Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=210960&r1=210959&r2=210960&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Fri Jun 13 18:47:38 2014
@@ -641,6 +641,8 @@ public:
 
   CFG *getParent() const { return Parent; }
 
+  void dump() const;
+
   void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
   void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
              bool ShowColors) const;

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=210960&r1=210959&r2=210960&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Fri Jun 13 18:47:38 2014
@@ -4356,6 +4356,10 @@ void CFGBlock::dump(const CFG* cfg, cons
   print(llvm::errs(), cfg, LO, ShowColors);
 }
 
+void CFGBlock::dump() const {
+  dump(getParent(), LangOptions(), false);
+}
+
 /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
 ///   Generally this will only be called from CFG::print.
 void CFGBlock::print(raw_ostream &OS, const CFG* cfg,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=210960&r1=210959&r2=210960&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Fri Jun 13 18:47:38 2014
@@ -2340,14 +2340,27 @@ CFRefLeakReport::CFRefLeakReport(CFRefBu
 
   // Get the SourceLocation for the allocation site.
   // FIXME: This will crash the analyzer if an allocation comes from an
-  // implicit call. (Currently there are no such allocations in Cocoa, though.)
-  const Stmt *AllocStmt;
+  // implicit call (ex: a destructor call).
+  // (Currently there are no such allocations in Cocoa, though.)
+  const Stmt *AllocStmt = 0;
   ProgramPoint P = AllocNode->getLocation();
   if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
     AllocStmt = Exit->getCalleeContext()->getCallSite();
-  else
-    AllocStmt = P.castAs<PostStmt>().getStmt();
-  assert(AllocStmt && "All allocations must come from explicit calls");
+  else {
+    // We are going to get a BlockEdge when the leak and allocation happen in
+    // different, non-nested frames (contexts). For example, the case where an
+    // allocation happens in a block that captures a reference to it and
+    // that reference is overwritten/dropped by another call to the block.
+    if (Optional<BlockEdge> Edge = P.getAs<BlockEdge>()) {
+      if (Optional<CFGStmt> St = Edge->getDst()->front().getAs<CFGStmt>()) {
+        AllocStmt = St->getStmt();
+      }
+    }
+    else {
+      AllocStmt = P.castAs<PostStmt>().getStmt();
+    }
+  }
+  assert(AllocStmt && "Cannot find allocation statement");
 
   PathDiagnosticLocation AllocLocation =
     PathDiagnosticLocation::createBegin(AllocStmt, SMgr,

Added: cfe/trunk/test/Analysis/objc-radar17039661.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/objc-radar17039661.m?rev=210960&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/objc-radar17039661.m (added)
+++ cfe/trunk/test/Analysis/objc-radar17039661.m Fri Jun 13 18:47:38 2014
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -verify -fblocks %s
+
+ at class NSString;
+typedef long NSInteger;
+typedef unsigned char BOOL;
+ at interface NSObject {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+ at end
+ at interface NSNumber : NSObject
++ (NSNumber *)numberWithInteger:(NSInteger)value __attribute__((availability(ios,introduced=2.0)));
+ at end
+
+NSInteger *inoutIntegerValueGlobal;
+NSInteger *inoutIntegerValueGlobal2;
+NSString *traitNameGlobal;
+static BOOL cond;
+
+static inline void reallyPerformAction(void (^integerHandler)(NSInteger *inoutIntegerValue, NSString *traitName)) {
+  integerHandler(inoutIntegerValueGlobal, traitNameGlobal);
+  integerHandler(inoutIntegerValueGlobal2,traitNameGlobal);
+}
+
+static inline BOOL performAction(NSNumber *(^action)(NSNumber *traitValue)) {
+  __attribute__((__blocks__(byref))) BOOL didFindTrait = 0;
+  reallyPerformAction(^(NSInteger *inoutIntegerValue,NSString *traitName) {
+
+    if (cond) {
+
+      NSNumber *traitValue = @(*inoutIntegerValue);
+
+      NSNumber *newTraitValue = action(traitValue);
+
+      if (traitValue != newTraitValue) {
+        *inoutIntegerValue = newTraitValue ? *inoutIntegerValue : *inoutIntegerValue;
+      }
+      didFindTrait = 1;
+    }
+
+  });
+  return didFindTrait;
+}
+
+void runTest() {
+  __attribute__((__blocks__(byref))) NSNumber *builtinResult = ((NSNumber *)0);
+  BOOL wasBuiltinTrait = performAction(^(NSNumber *traitValue) {
+    builtinResult = [traitValue retain]; // expected-warning {{Potential leak of an object}}
+
+    return traitValue;
+  });
+  if (wasBuiltinTrait) {
+    [builtinResult autorelease];
+    return;
+  } else {
+    return;
+  }
+}





More information about the cfe-commits mailing list