From: Ted Kremenek Date: Thu, 20 Jan 2011 17:09:48 +0000 (+0000) Subject: Enhance AnalysisConsumer to also visit functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=14cc9451de4a9539bf79e4e5d63248c2377426db;p=clang Enhance AnalysisConsumer to also visit functions and methods defined within 'namespace X { ... }'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123921 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp index ee4eae2ebf..ae8732a857 100644 --- a/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp @@ -198,6 +198,8 @@ public: } virtual void HandleTranslationUnit(ASTContext &C); + void HandleDeclContext(ASTContext &C, DeclContext *dc); + void HandleCode(Decl *D, Actions& actions); }; } // end anonymous namespace @@ -206,55 +208,61 @@ public: // AnalysisConsumer implementation. //===----------------------------------------------------------------------===// -void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { - - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - - for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end(); +void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) { + for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end(); I != E; ++I) { Decl *D = *I; - + switch (D->getKind()) { - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: { - FunctionDecl* FD = cast(D); - // We skip function template definitions, as their semantics is - // only determined when they are instantiated. - if (FD->isThisDeclarationADefinition() && - !FD->isDependentContext()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) - break; - DisplayFunction(FD); - HandleCode(FD, FunctionActions); + case Decl::Namespace: { + HandleDeclContext(C, cast(D)); + break; } - break; - } - - case Decl::ObjCImplementation: { - ObjCImplementationDecl* ID = cast(*I); - HandleCode(ID, ObjCImplementationActions); - - for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), - ME = ID->meth_end(); MI != ME; ++MI) { - if ((*MI)->isThisDeclarationADefinition()) { + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + case Decl::CXXMethod: + case Decl::Function: { + FunctionDecl* FD = cast(D); + // We skip function template definitions, as their semantics is + // only determined when they are instantiated. + if (FD->isThisDeclarationADefinition() && + !FD->isDependentContext()) { if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) + FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) break; - DisplayFunction(*MI); - HandleCode(*MI, ObjCMethodActions); + DisplayFunction(FD); + HandleCode(FD, FunctionActions); } + break; } - break; + + case Decl::ObjCImplementation: { + ObjCImplementationDecl* ID = cast(*I); + HandleCode(ID, ObjCImplementationActions); + + for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), + ME = ID->meth_end(); MI != ME; ++MI) { + if ((*MI)->isThisDeclarationADefinition()) { + if (!Opts.AnalyzeSpecificFunction.empty() && + Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) + break; + DisplayFunction(*MI); + HandleCode(*MI, ObjCMethodActions); + } + } + break; + } + + default: + break; } + } +} - default: - break; - } - } +void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { + TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + HandleDeclContext(C, TU); for (TUActions::iterator I = TranslationUnitActions.begin(), E = TranslationUnitActions.end(); I != E; ++I) { diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp index b21ffad6c5..b5fc05028f 100644 --- a/test/Analysis/dead-stores.cpp +++ b/test/Analysis/dead-stores.cpp @@ -100,3 +100,15 @@ static void test_new(unsigned n) { char **p = new char* [n]; // expected-warning{{never read}} } +//===----------------------------------------------------------------------===// +// Dead stores in namespaces. +//===----------------------------------------------------------------------===// + +namespace foo { + int test_4(int x) { + x = 2; // expected-warning{{Value stored to 'x' is never read}} + x = 2; + return x; + } +} +