diff options
Diffstat (limited to 'lib/Analysis/CheckObjCUnusedIVars.cpp')
-rw-r--r-- | lib/Analysis/CheckObjCUnusedIVars.cpp | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp index 0063c40482a0e..1a900f8976783 100644 --- a/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -24,47 +24,56 @@ using namespace clang; enum IVarState { Unused, Used }; -typedef llvm::DenseMap<ObjCIvarDecl*,IVarState> IvarUsageMap; +typedef llvm::DenseMap<const ObjCIvarDecl*,IVarState> IvarUsageMap; -static void Scan(IvarUsageMap& M, Stmt* S) { +static void Scan(IvarUsageMap& M, const Stmt* S) { if (!S) return; - - if (ObjCIvarRefExpr* Ex = dyn_cast<ObjCIvarRefExpr>(S)) { - 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; + 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::child_iterator I=S->child_begin(), E=S->child_end(); I!=E;++I) + + for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I) Scan(M, *I); } -static void Scan(IvarUsageMap& M, ObjCPropertyImplDecl* D) { +static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) { if (!D) return; - - ObjCIvarDecl* ID = D->getPropertyIvarDecl(); + + const ObjCIvarDecl* ID = D->getPropertyIvarDecl(); if (!ID) return; - + IvarUsageMap::iterator I = M.find(ID); - if (I != M.end()) I->second = Used; + if (I != M.end()) + I->second = Used; } -void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { +void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D, + BugReporter &BR) { - ObjCInterfaceDecl* ID = D->getClassInterface(); + const ObjCInterfaceDecl* ID = D->getClassInterface(); IvarUsageMap M; // Iterate over the ivars. - for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end(); - I!=E; ++I) { - - ObjCIvarDecl* ID = *I; - + for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), + E=ID->ivar_end(); I!=E; ++I) { + + const ObjCIvarDecl* ID = *I; + // Ignore ivars that aren't private. if (ID->getAccessControl() != ObjCIvarDecl::Private) continue; @@ -72,31 +81,31 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { // Skip IB Outlets. if (ID->getAttr<IBOutletAttr>()) continue; - + M[ID] = Unused; } if (M.empty()) return; - + // Now scan the methods for accesses. for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), - E = D->instmeth_end(); I!=E; ++I) + E = D->instmeth_end(); I!=E; ++I) Scan(M, (*I)->getBody()); - + // Scan for @synthesized property methods that act as setters/getters // to an ivar. for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), E = D->propimpl_end(); I!=E; ++I) - Scan(M, *I); - + Scan(M, *I); + // Find ivars that are unused. for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I) if (I->second == Unused) { std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "Instance variable '" << I->first->getNameAsString() - << "' in class '" << ID->getNameAsString() + << "' in class '" << ID->getNameAsString() << "' is never used by the methods in its @implementation " "(although it may be used by category methods)."; @@ -104,4 +113,3 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { os.str().c_str(), I->first->getLocation()); } } - |