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