From: Ted Kremenek Date: Wed, 23 Jul 2008 00:45:26 +0000 (+0000) Subject: Add prototype implementation of unused ivar check. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=395aaf20d6e1ab04741562dc6b7d47164bcbd87e;p=clang Add prototype implementation of unused ivar check. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53942 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/Analyses.def b/Driver/Analyses.def index 623a2475d6..841f0c1da1 100644 --- a/Driver/Analyses.def +++ b/Driver/Analyses.def @@ -33,6 +33,9 @@ ANALYSIS(WarnObjCMethSigs, "warn-objc-methodsigs", ANALYSIS(WarnObjCDealloc, "warn-objc-missing-dealloc", "Warn about Objective-C classes that lack a correct implementation of -dealloc", ObjCImplementation) + +ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars", + "Warn about private ivars that are never used", ObjCImplementation) ANALYSIS(CheckerSimple, "checker-simple", "Perform simple path-sensitive checks.", Code) diff --git a/Driver/AnalysisConsumer.cpp b/Driver/AnalysisConsumer.cpp index deb7a85006..134f6d6533 100644 --- a/Driver/AnalysisConsumer.cpp +++ b/Driver/AnalysisConsumer.cpp @@ -393,6 +393,11 @@ static void ActionWarnObjCDealloc(AnalysisManager& mgr) { mgr.getLangOptions(), BR); } +static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) { + BugReporter BR(mgr); + CheckObjCUnusedIvar(cast(mgr.getCodeDecl()), BR); +} + static void ActionWarnObjCMethSigs(AnalysisManager& mgr) { BugReporter BR(mgr); diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index 8da144ebce..23610f9a2d 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -45,6 +45,7 @@ void CheckObjCDealloc(ObjCImplementationDecl* D, const LangOptions& L, BugReporter& BR); void CheckObjCInstMethSignature(ObjCImplementationDecl* ID, BugReporter& BR); +void CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR); void RegisterAppleChecks(GRExprEngine& Eng); diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp new file mode 100644 index 0000000000..4eb273314d --- /dev/null +++ b/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -0,0 +1,87 @@ +//==- CheckObjCUnusedIVars.cpp - Check for unused ivars ----------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a CheckObjCUnusedIvars, a checker that +// analyzes an Objective-C class's interface/implementation to determine if it +// has any ivars that are never accessed. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/LocalCheckers.h" +#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathSensitive/BugReporter.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/LangOptions.h" +#include + +using namespace clang; + +enum IVarState { Unused, Used }; +typedef llvm::DenseMap IvarUsageMap; + +static void Scan(IvarUsageMap& M, Stmt* S) { + if (!S) + return; + + if (ObjCIvarRefExpr* Ex = dyn_cast(S)) { + ObjCIvarDecl* D = Ex->getDecl(); + IvarUsageMap::iterator I = M.find(D); + if (I != M.end()) I->second = Used; + } + else + for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E;++I) + Scan(M, *I); +} + +void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { + + 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; + + // Ignore ivars that aren't private. + ObjCIvarDecl::AccessControl ac = ID->getAccessControl(); + if (!(ac == ObjCIvarDecl::None || ac == ObjCIvarDecl::Private)) + continue; + + if (ID->getAttr() == 0) + 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) + Scan(M, (*I)->getBody()); + + // Find ivars that are unused. + for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I) + if (I->second == Unused) { + + std::ostringstream os; + os << "Private ivar '" << I->first->getName() << "' is never used."; + + BR.EmitBasicReport("unused ivar", + os.str().c_str(), I->first->getLocation()); + } +} +