[cfe-commits] r52996 - in /cfe/trunk: Driver/ASTConsumers.cpp Driver/ASTConsumers.h Driver/AnalysisConsumer.cpp Driver/AnalysisConsumer.h Driver/clang.cpp test/Analysis/conditional-op-missing-lhs.c
Ted Kremenek
kremenek at apple.com
Tue Jul 1 17:03:09 PDT 2008
Author: kremenek
Date: Tue Jul 1 19:03:09 2008
New Revision: 52996
URL: http://llvm.org/viewvc/llvm-project?rev=52996&view=rev
Log:
Added AnalysisConsumer, a meta-level ASTConsumer class to drive various
analyses. This potentially is the primordial origins of a Clang-equivalent
"PassManager".
The new AnalysisConsumer interface allows multiple analyses to be run from a
single invocation of Clang.
Migrated the logic of "-warn-dead-stores" and "-warn-uninit-values" to use the
new AnalysisConsumer interface. The new interface results in a significant code
reduction to incorporate an analysis into the Driver.
Updated a test case to (correctly) acknowledge that it contains a dead store
(this check wasn't being performed because it was previously masked by
-warn-uninit-values).
Added:
cfe/trunk/Driver/AnalysisConsumer.cpp
cfe/trunk/Driver/AnalysisConsumer.h
Modified:
cfe/trunk/Driver/ASTConsumers.cpp
cfe/trunk/Driver/ASTConsumers.h
cfe/trunk/Driver/clang.cpp
cfe/trunk/test/Analysis/conditional-op-missing-lhs.c
Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=52996&r1=52995&r2=52996&view=diff
==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Tue Jul 1 19:03:09 2008
@@ -635,58 +635,6 @@
}
//===----------------------------------------------------------------------===//
-// DeadStores - run checker to locate dead stores in a function
-
-namespace {
- class DeadStoreVisitor : public CFGVisitor {
- Diagnostic &Diags;
- ASTContext *Ctx;
- public:
- DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
- virtual void Initialize(ASTContext &Context) {
- Ctx = &Context;
- }
-
- virtual void VisitCFG(CFG& C, Decl& CD) {
- llvm::OwningPtr<ParentMap> PM(new ParentMap(CD.getCodeBody()));
- CheckDeadStores(C, *Ctx, *PM, Diags);
- }
-
- virtual bool printFuncDeclStart() { return false; }
- };
-} // end anonymous namespace
-
-ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
- return new DeadStoreVisitor(Diags);
-}
-
-//===----------------------------------------------------------------------===//
-// Unitialized Values - run checker to flag potential uses of uninitalized
-// variables.
-
-namespace {
- class UninitValsVisitor : public CFGVisitor {
- Diagnostic &Diags;
- ASTContext *Ctx;
- public:
- UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
- virtual void Initialize(ASTContext &Context) {
- Ctx = &Context;
- }
-
- virtual void VisitCFG(CFG& C, Decl&) {
- CheckUninitializedValues(C, *Ctx, Diags);
- }
-
- virtual bool printFuncDeclStart() { return false; }
- };
-} // end anonymous namespace
-
-ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
- return new UninitValsVisitor(Diags);
-}
-
-//===----------------------------------------------------------------------===//
// CheckerConsumer - Generic Driver for running intra-procedural path-sensitive
// analyses.
Modified: cfe/trunk/Driver/ASTConsumers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.h?rev=52996&r1=52995&r2=52996&view=diff
==============================================================================
--- cfe/trunk/Driver/ASTConsumers.h (original)
+++ cfe/trunk/Driver/ASTConsumers.h Tue Jul 1 19:03:09 2008
@@ -30,7 +30,6 @@
class Preprocessor;
class PreprocessorFactory;
-
ASTConsumer *CreateASTPrinter(std::ostream* OS = NULL);
ASTConsumer *CreateASTDumper();
@@ -41,10 +40,6 @@
ASTConsumer *CreateLiveVarAnalyzer(const std::string& fname);
-ASTConsumer *CreateDeadStoreChecker(Diagnostic &Diags);
-
-ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags);
-
ASTConsumer *CreateGRSimpleVals(Diagnostic &Diags,
Preprocessor* PP, PreprocessorFactory* PPF,
const std::string& Function,
@@ -75,4 +70,6 @@
} // end clang namespace
+#include "AnalysisConsumer.h"
+
#endif
Added: cfe/trunk/Driver/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/AnalysisConsumer.cpp?rev=52996&view=auto
==============================================================================
--- cfe/trunk/Driver/AnalysisConsumer.cpp (added)
+++ cfe/trunk/Driver/AnalysisConsumer.cpp Tue Jul 1 19:03:09 2008
@@ -0,0 +1,248 @@
+//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// "Meta" ASTConsumer for running different source analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTConsumers.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "clang/AST/CFG.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/PathDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+
+using namespace clang;
+
+
+//===----------------------------------------------------------------------===//
+// Basic type definitions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+ class AnalysisManager;
+ typedef void (*CodeAction)(AnalysisManager& Mgr);
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer declaration.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+ class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
+ typedef llvm::ImmutableList<CodeAction> Actions;
+ Actions FunctionActions;
+ Actions ObjCMethodActions;
+
+ Actions::Factory F;
+
+ public:
+ const bool Visualize;
+ const bool TrimGraph;
+ const LangOptions& LOpts;
+ Diagnostic &Diags;
+ ASTContext* Ctx;
+ Preprocessor* PP;
+ PreprocessorFactory* PPF;
+ const std::string HTMLDir;
+ const std::string FName;
+ llvm::OwningPtr<PathDiagnosticClient> PD;
+ bool AnalyzeAll;
+
+ AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
+ PreprocessorFactory* ppf,
+ const LangOptions& lopts,
+ const std::string& fname,
+ const std::string& htmldir,
+ bool visualize, bool trim, bool analyzeAll)
+ : FunctionActions(F.GetEmptyList()), ObjCMethodActions(F.GetEmptyList()),
+ Visualize(visualize), TrimGraph(trim), LOpts(lopts), Diags(diags),
+ Ctx(0), PP(pp), PPF(ppf),
+ HTMLDir(htmldir),
+ FName(fname),
+ AnalyzeAll(analyzeAll) {}
+
+ void addCodeAction(CodeAction action) {
+ FunctionActions = F.Concat(action, FunctionActions);
+ ObjCMethodActions = F.Concat(action, ObjCMethodActions);
+ }
+
+ virtual void Initialize(ASTContext &Context) {
+ Ctx = &Context;
+ }
+
+ virtual void HandleTopLevelDecl(Decl *D);
+ void HandleCode(Decl* D, Stmt* Body, Actions actions);
+ };
+
+
+ class VISIBILITY_HIDDEN AnalysisManager {
+ Decl* D;
+ Stmt* Body;
+ AnalysisConsumer& C;
+
+ llvm::OwningPtr<CFG> cfg;
+ llvm::OwningPtr<LiveVariables> liveness;
+ llvm::OwningPtr<ParentMap> PM;
+
+ public:
+ AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
+ : D(d), Body(b), C(c) {}
+
+
+ Decl* getCodeDecl() const { return D; }
+ Stmt* getBody() const { return Body; }
+
+ CFG* getCFG() {
+ if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
+ return cfg.get();
+ }
+
+ ParentMap* getParentMap() {
+ if (!PM) PM.reset(new ParentMap(getBody()));
+ return PM.get();
+ }
+
+ ASTContext& getContext() {
+ return *C.Ctx;
+ }
+
+ Diagnostic& getDiagnostic() {
+ return C.Diags;
+ }
+
+ LiveVariables* getLiveVariables() {
+ if (!liveness) liveness.reset(new LiveVariables(*getCFG()));
+ return liveness.get();
+ }
+ };
+
+} // end anonymous namespace
+
+namespace llvm {
+ template <> struct FoldingSetTrait<CodeAction> {
+ static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
+ ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
+ }
+ };
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer implementation.
+//===----------------------------------------------------------------------===//
+
+void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
+ switch (D->getKind()) {
+ case Decl::Function: {
+ FunctionDecl* FD = cast<FunctionDecl>(D);
+ Stmt* Body = FD->getBody();
+ if (Body) HandleCode(FD, Body, FunctionActions);
+ break;
+ }
+
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
+ Stmt* Body = MD->getBody();
+ if (Body) HandleCode(MD, Body, ObjCMethodActions);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
+
+ // Don't run the actions if an error has occured with parsing the file.
+ if (Diags.hasErrorOccurred())
+ return;
+
+ SourceLocation Loc = D->getLocation();
+
+ // Only run actions on declarations defined in actual source.
+ if (!Loc.isFileID())
+ return;
+
+ // Don't run the actions on declarations in header files unless
+ // otherwise specified.
+ if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
+ return;
+
+ // Create an AnalysisManager that will manage the state for analyzing
+ // this method/function.
+ AnalysisManager mgr(*this, D, Body);
+
+ // Dispatch on the actions.
+ for (Actions::iterator I = actions.begin(),
+ E = actions.end(); I != E; ++I)
+ ((*I).getHead())(mgr);
+}
+
+//===----------------------------------------------------------------------===//
+// Analyses
+//===----------------------------------------------------------------------===//
+
+static void ActionDeadStores(AnalysisManager& mgr) {
+ CheckDeadStores(*mgr.getCFG(), mgr.getContext(), *mgr.getParentMap(),
+ mgr.getDiagnostic());
+}
+
+static void ActionUninitVals(AnalysisManager& mgr) {
+ CheckUninitializedValues(*mgr.getCFG(), mgr.getContext(),
+ mgr.getDiagnostic());
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer creation.
+//===----------------------------------------------------------------------===//
+
+ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
+ Diagnostic &diags, Preprocessor* pp,
+ PreprocessorFactory* ppf,
+ const LangOptions& lopts,
+ const std::string& fname,
+ const std::string& htmldir,
+ bool visualize, bool trim,
+ bool analyzeAll) {
+
+ llvm::OwningPtr<AnalysisConsumer>
+ C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
+ visualize, trim, analyzeAll));
+
+ for ( ; Beg != End ; ++Beg)
+ switch (*Beg) {
+ case WarnDeadStores:
+ C->addCodeAction(&ActionDeadStores);
+ break;
+
+ case WarnUninitVals:
+ C->addCodeAction(&ActionUninitVals);
+ break;
+
+ default: break;
+ }
+
+ return C.take();
+}
+
Added: cfe/trunk/Driver/AnalysisConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/AnalysisConsumer.h?rev=52996&view=auto
==============================================================================
--- cfe/trunk/Driver/AnalysisConsumer.h (added)
+++ cfe/trunk/Driver/AnalysisConsumer.h Tue Jul 1 19:03:09 2008
@@ -0,0 +1,34 @@
+//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// "Meta" ASTConsumer for running different source analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DRIVER_ANALYSISCONSUMER_H
+#define DRIVER_ANALYSISCONSUMER_H
+
+namespace clang {
+
+enum Analyses {
+ WarnDeadStores,
+ WarnUninitVals
+};
+
+ASTConsumer* CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
+ Diagnostic &diags, Preprocessor* pp,
+ PreprocessorFactory* ppf,
+ const LangOptions& lopts,
+ const std::string& fname,
+ const std::string& htmldir,
+ bool visualize, bool trim,
+ bool analyzeAll);
+} // end clang namespace
+
+#endif
Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=52996&r1=52995&r2=52996&view=diff
==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Tue Jul 1 19:03:09 2008
@@ -78,16 +78,14 @@
AnalysisGRSimpleVals, // Perform graph-reachability constant prop.
AnalysisGRSimpleValsView, // Visualize results of path-sens. analysis.
CheckerCFRef, // Run the Core Foundation Ref. Count Checker.
- WarnDeadStores, // Run DeadStores checker on parsed ASTs.
- WarnDeadStoresCheck, // Check diagnostics for "DeadStores".
- WarnUninitVals, // Run UnitializedVariables checker.
TestSerialization, // Run experimental serialization code.
ParsePrintCallbacks, // Parse and print each callback.
ParseSyntaxOnly, // Parse and perform semantic analysis.
ParseNoop, // Parse with noop callbacks.
RunPreprocessorOnly, // Just lex, no output.
PrintPreprocessedInput, // -E mode.
- DumpTokens // Token dump mode.
+ DumpTokens, // Token dump mode.
+ RunAnalysis // Run one or more source code analyses.
};
static llvm::cl::opt<ProgActions>
@@ -120,10 +118,6 @@
"Run parser, then build and view CFGs with Graphviz"),
clEnumValN(AnalysisLiveVariables, "dump-live-variables",
"Print results of live variable analysis"),
- clEnumValN(WarnDeadStores, "warn-dead-stores",
- "Flag warnings of stores to dead variables"),
- clEnumValN(WarnUninitVals, "warn-uninit-values",
- "Flag warnings of uses of unitialized variables"),
clEnumValN(AnalysisGRSimpleVals, "checker-simple",
"Perform path-sensitive constant propagation"),
clEnumValN(CheckerCFRef, "checker-cfref",
@@ -181,6 +175,15 @@
llvm::cl::desc("Force the static analyzer to analyze "
"functions defined in header files"));
+static llvm::cl::list<Analyses>
+AnalysisList(llvm::cl::desc("Available Source Code Analyses:"),
+llvm::cl::values(
+clEnumValN(WarnDeadStores, "warn-dead-stores",
+ "Flag warnings of stores to dead variables"),
+clEnumValN(WarnUninitVals, "warn-uninit-values",
+ "Flag warnings of uses of unitialized variables"),
+clEnumValEnd));
+
//===----------------------------------------------------------------------===//
// Language Options
//===----------------------------------------------------------------------===//
@@ -1199,12 +1202,6 @@
case AnalysisLiveVariables:
return CreateLiveVarAnalyzer(AnalyzeSpecificFunction);
- case WarnDeadStores:
- return CreateDeadStoreChecker(Diag);
-
- case WarnUninitVals:
- return CreateUnitValsChecker(Diag);
-
case AnalysisGRSimpleVals:
return CreateGRSimpleVals(Diag, PP, PPF, AnalyzeSpecificFunction,
OutputFile, VisualizeEG, TrimGraph, AnalyzeAll);
@@ -1228,6 +1225,15 @@
case RewriteObjC:
return CreateCodeRewriterTest(InFile, OutputFile, Diag, LangOpts);
+
+ case RunAnalysis:
+ assert (!AnalysisList.empty());
+ return CreateAnalysisConsumer(&AnalysisList[0],
+ &AnalysisList[0]+AnalysisList.size(),
+ Diag, PP, PPF, LangOpts,
+ AnalyzeSpecificFunction,
+ OutputFile, VisualizeEG, TrimGraph,
+ AnalyzeAll);
}
}
@@ -1485,6 +1491,11 @@
exit(1);
}
+ // Are we invoking one or more source analyses?
+ if (!AnalysisList.empty() && ProgAction == ParseSyntaxOnly)
+ ProgAction = RunAnalysis;
+
+
llvm::OwningPtr<SourceManager> SourceMgr;
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
Modified: cfe/trunk/test/Analysis/conditional-op-missing-lhs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/conditional-op-missing-lhs.c?rev=52996&r1=52995&r2=52996&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/conditional-op-missing-lhs.c (original)
+++ cfe/trunk/test/Analysis/conditional-op-missing-lhs.c Tue Jul 1 19:03:09 2008
@@ -4,7 +4,7 @@
{
int i;
- int j = i ? : 1; // expected-warning{{use of uninitialized variable}}
+ int j = i ? : 1; // expected-warning{{use of uninitialized variable}} //expected-warning{{Value stored to 'j' is never read}}
}
void *f2(int *i)
More information about the cfe-commits
mailing list