diff options
| author | Ted Kremenek <kremenek@apple.com> | 2009-08-07 21:13:23 +0000 |
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2009-08-07 21:13:23 +0000 |
| commit | 0e8e1fde255319bbf491c3fb204419ae2650375d (patch) | |
| tree | 891fa94917d65e909cd1c6dc31c2685fa1befcd1 | |
| parent | d0470d74dfec5c6e4e921c47ecce771e904f8f98 (diff) | |
| download | bcm5719-llvm-0e8e1fde255319bbf491c3fb204419ae2650375d.tar.gz bcm5719-llvm-0e8e1fde255319bbf491c3fb204419ae2650375d.zip | |
Fix: <rdar://problem/7075531> static analyzer wrongly detects unused ivars used in blocks
llvm-svn: 78409
| -rw-r--r-- | clang/lib/Analysis/CheckObjCUnusedIVars.cpp | 10 | ||||
| -rw-r--r-- | clang/test/Analysis/unused-ivars.m | 45 |
2 files changed, 48 insertions, 7 deletions
diff --git a/clang/lib/Analysis/CheckObjCUnusedIVars.cpp b/clang/lib/Analysis/CheckObjCUnusedIVars.cpp index dbc90d65c30..3a69e00499d 100644 --- a/clang/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/clang/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -30,14 +30,20 @@ static void Scan(IvarUsageMap& M, const Stmt* S) { if (!S) return; - if (const ObjCIvarRefExpr* Ex = dyn_cast<ObjCIvarRefExpr>(S)) { - const ObjCIvarDecl* D = Ex->getDecl(); + if (const ObjCIvarRefExpr *Ex = dyn_cast<ObjCIvarRefExpr>(S)) { + const ObjCIvarDecl *D = Ex->getDecl(); IvarUsageMap::iterator I = M.find(D); if (I != M.end()) I->second = Used; return; } + // Blocks can reference an instance variable of a class. + if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) { + Scan(M, BE->getBody()); + return; + } + for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I) Scan(M, *I); } diff --git a/clang/test/Analysis/unused-ivars.m b/clang/test/Analysis/unused-ivars.m index 632b395c3e0..aacd44e7e67 100644 --- a/clang/test/Analysis/unused-ivars.m +++ b/clang/test/Analysis/unused-ivars.m @@ -1,10 +1,45 @@ -// RUN: clang-cc -analyze -warn-objc-unused-ivars %s -verify +// RUN: clang-cc -triple x86_64-apple-darwin10 -analyze -warn-objc-unused-ivars %s -verify -@interface A -{ - @private int x; // expected-warning {{Instance variable 'x' in class 'A' is never used}} +//===--- BEGIN: Delta-debugging reduced headers. --------------------------===// + +@protocol NSObject +- (id)retain; +- (oneway void)release; +@end +@interface NSObject <NSObject> {} +- (id)init; ++ (id)alloc; +@end + +//===--- END: Delta-debugging reduced headers. ----------------------------===// + +// This test case tests the basic functionality of the unused ivar test. +@interface TestA { +@private + int x; // expected-warning {{Instance variable 'x' in class 'TestA' is never used}} } @end +@implementation TestA @end -@implementation A @end +// This test case tests whether the unused ivar check handles blocks that +// reference an instance variable. (<rdar://problem/7075531>) +@interface TestB : NSObject { +@private + id _ivar; // no-warning +} +@property (readwrite,retain) id ivar; +@end + +@implementation TestB +- (id)ivar { + __attribute__((__blocks__(byref))) id value = ((void*)0); + void (^b)() = ^{ value = _ivar; }; + b(); + return value; +} +- (void)setIvar:(id)newValue { + void (^b)() = ^{ [_ivar release]; _ivar = [newValue retain]; }; + b(); +} +@end |

