summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-08-07 21:13:23 +0000
committerTed Kremenek <kremenek@apple.com>2009-08-07 21:13:23 +0000
commit0e8e1fde255319bbf491c3fb204419ae2650375d (patch)
tree891fa94917d65e909cd1c6dc31c2685fa1befcd1
parentd0470d74dfec5c6e4e921c47ecce771e904f8f98 (diff)
downloadbcm5719-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.cpp10
-rw-r--r--clang/test/Analysis/unused-ivars.m45
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
OpenPOWER on IntegriCloud