From: Ted Kremenek Date: Fri, 7 Aug 2009 21:13:23 +0000 (+0000) Subject: Fix: static analyzer wrongly detects unused ivars used in... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=35ffcf3c2a054ee124fe8d47152c5d1bcdf86261;p=clang Fix: static analyzer wrongly detects unused ivars used in blocks git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78409 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp index dbc90d65c3..3a69e00499 100644 --- a/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/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(S)) { - const ObjCIvarDecl* D = Ex->getDecl(); + if (const ObjCIvarRefExpr *Ex = dyn_cast(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(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/test/Analysis/unused-ivars.m b/test/Analysis/unused-ivars.m index 632b395c3e..aacd44e7e6 100644 --- a/test/Analysis/unused-ivars.m +++ b/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 {} +- (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. () +@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