diff options
-rw-r--r-- | Driver/ASTConsumers.cpp | 188 | ||||
-rw-r--r-- | Driver/ASTConsumers.h | 7 | ||||
-rw-r--r-- | Driver/clang.cpp | 21 | ||||
-rw-r--r-- | include/clang/Analysis/LocalCheckers.h | 9 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 19 | ||||
-rw-r--r-- | lib/Analysis/GRSimpleVals.cpp | 31 | ||||
-rw-r--r-- | test/Analysis-Apple/NSString.m | 2 | ||||
-rw-r--r-- | test/Analysis-Apple/uninit-msg-expr.m | 2 | ||||
-rw-r--r-- | test/Analysis/null-deref-ps.c | 2 | ||||
-rw-r--r-- | test/Analysis/stack-addr-ps.c | 2 |
10 files changed, 131 insertions, 152 deletions
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 3c104150f1..4537a7f347 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -22,6 +22,8 @@ #include "clang/AST/CFG.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/LocalCheckers.h" +#include "clang/Analysis/PathSensitive/GRTransferFuncs.h" +#include "clang/Analysis/PathSensitive/GRExprEngine.h" #include "llvm/Support/Streams.h" #include "llvm/Support/Timer.h" #include "llvm/ADT/OwningPtr.h" @@ -628,123 +630,143 @@ ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) { } //===----------------------------------------------------------------------===// -// GRSimpleVals - Perform intra-procedural, path-sensitive constant propagation. +// CheckeRConsumer - Generic Driver for running intra-procedural path-sensitive +// analyses. namespace { - class GRSimpleValsVisitor : public CFGVisitor { - Diagnostic &Diags; - ASTContext* Ctx; - const std::string& HTMLDir; - bool Visualize; - bool TrimGraph; - public: - GRSimpleValsVisitor(Diagnostic &diags, const std::string& fname, - const std::string& htmldir, - bool visualize, bool trim) - : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir), - Visualize(visualize), TrimGraph(trim) {} - - virtual void Initialize(ASTContext &Context) { Ctx = &Context; } - virtual void VisitCFG(CFG& C, Decl&); - virtual bool printFuncDeclStart() { return false; } - }; -} // end anonymous namespace - -ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags, - const std::string& FunctionName, - const std::string& HTMLDir, - bool Visualize, bool TrimGraph) { - return new GRSimpleValsVisitor(Diags, FunctionName, HTMLDir, - Visualize, TrimGraph); -} +class CheckerConsumer : public CFGVisitor { + Diagnostic &Diags; + ASTContext* Ctx; + const std::string& HTMLDir; + bool Visualize; + bool TrimGraph; + llvm::OwningPtr<PathDiagnosticClient> PD; +public: + CheckerConsumer(Diagnostic &diags, const std::string& fname, + const std::string& htmldir, + bool visualize, bool trim) + : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir), + Visualize(visualize), TrimGraph(trim) {} + + virtual void Initialize(ASTContext &Context) { Ctx = &Context; } + virtual void VisitCFG(CFG& C, Decl&); + virtual bool printFuncDeclStart() { return false; } + + virtual const char* getCheckerName() = 0; + virtual GRTransferFuncs* getTransferFunctions() = 0; +}; +} // end anonymous namespace -void GRSimpleValsVisitor::VisitCFG(CFG& C, Decl& CD) { +void CheckerConsumer::VisitCFG(CFG& C, Decl& CD) { if (Diags.hasErrorOccurred()) return; SourceLocation Loc = CD.getLocation(); - + if (!Loc.isFileID() || - Loc.getFileID() != Ctx->getSourceManager().getMainFileID()) + Loc.getFileID() != Ctx->getSourceManager().getMainFileID()) return; + + // Lazily create the diagnostic client. + + if (!HTMLDir.empty() && PD.get() == NULL) + PD.reset(CreateHTMLDiagnosticClient(HTMLDir)); + if (!Visualize) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(&CD)) { llvm::cerr << "ANALYZE: " - << Ctx->getSourceManager().getSourceName(FD->getLocation()) - << ' ' - << FD->getIdentifier()->getName() - << '\n'; + << Ctx->getSourceManager().getSourceName(FD->getLocation()) + << ' ' + << FD->getIdentifier()->getName() + << '\n'; } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(&CD)) { llvm::cerr << "ANALYZE (ObjC Method): " - << Ctx->getSourceManager().getSourceName(MD->getLocation()) - << " '" - << MD->getSelector().getName() << "'\n"; + << Ctx->getSourceManager().getSourceName(MD->getLocation()) + << " '" + << MD->getSelector().getName() << "'\n"; } - -#if 0 - llvm::Timer T("GRSimpleVals"); - T.startTimer(); - unsigned size = RunGRSimpleVals(C, CD, *Ctx, Diags, NULL, false, false); - T.stopTimer(); - llvm::cerr << size << ' ' << T.getWallTime() << '\n'; -#else - llvm::OwningPtr<PathDiagnosticClient> PD; - - if (!HTMLDir.empty()) - PD.reset(CreateHTMLDiagnosticClient(HTMLDir)); - - RunGRSimpleVals(C, CD, *Ctx, Diags, PD.get(), false, false); -#endif } - else { + else llvm::cerr << '\n'; - RunGRSimpleVals(C, CD, *Ctx, Diags, NULL, Visualize, TrimGraph); - } + + // Construct the analysis engine. + GRExprEngine Eng(C, CD, *Ctx); + + // Set base transfer functions. + llvm::OwningPtr<GRTransferFuncs> TF(getTransferFunctions()); + Eng.setTransferFunctions(TF.get()); + + // Execute the worklist algorithm. + Eng.ExecuteWorkList(); + + // Display warnings. + Eng.EmitWarnings(Diags, PD.get()); + +#ifndef NDEBUG + if (Visualize) Eng.ViewGraph(TrimGraph); +#endif } - //===----------------------------------------------------------------------===// -// Core Foundation Reference Counting Checker +// GRSimpleVals - Perform intra-procedural, path-sensitive constant propagation. namespace { - class CFRefCountCheckerVisitor : public CFGVisitor { - Diagnostic &Diags; - ASTContext* Ctx; - const std::string& HTMLDir; - - public: - CFRefCountCheckerVisitor(Diagnostic &diags, const std::string& fname, - const std::string& htmldir) - : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir) {} - - virtual void Initialize(ASTContext &Context) { Ctx = &Context; } - virtual void VisitCFG(CFG& C, Decl&); - virtual bool printFuncDeclStart() { return false; } - }; -} // end anonymous namespace +class GRSimpleValsVisitor : public CheckerConsumer { +public: + GRSimpleValsVisitor(Diagnostic &diags, const std::string& fname, + const std::string& htmldir, + bool visualize, bool trim) + : CheckerConsumer(diags, fname, htmldir, visualize, trim) {} + virtual const char* getCheckerName() { return "GRSimpleVals"; } + + virtual GRTransferFuncs* getTransferFunctions() { + return MakeGRSimpleValsTF(); + } +}; +} // end anonymous namespace -ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags, +ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags, const std::string& FunctionName, - const std::string& HTMLDir) { + const std::string& HTMLDir, + bool Visualize, bool TrimGraph) { - return new CFRefCountCheckerVisitor(Diags, FunctionName, HTMLDir); + return new GRSimpleValsVisitor(Diags, FunctionName, HTMLDir, + Visualize, TrimGraph); } -void CFRefCountCheckerVisitor::VisitCFG(CFG& C, Decl& CD) { - - SourceLocation Loc = CD.getLocation(); + +//===----------------------------------------------------------------------===// +// Core Foundation Reference Counting Checker + +namespace { +class CFRefCountCheckerVisitor : public CheckerConsumer { +public: + CFRefCountCheckerVisitor(Diagnostic &diags, const std::string& fname, + const std::string& htmldir, + bool visualize, bool trim) + : CheckerConsumer(diags, fname, htmldir, visualize, trim) {} - if (!Loc.isFileID() || - Loc.getFileID() != Ctx->getSourceManager().getMainFileID()) - return; - - CheckCFRefCount(C, CD, *Ctx, Diags, NULL); + virtual const char* getCheckerName() { return "CFRefCountChecker"; } + + virtual GRTransferFuncs* getTransferFunctions() { + return MakeCFRefCountTF(); + } +}; +} // end anonymous namespace + +ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags, + const std::string& FunctionName, + const std::string& HTMLDir, + bool Visualize, bool TrimGraph) { + + return new CFRefCountCheckerVisitor(Diags, FunctionName, HTMLDir, + Visualize, TrimGraph); } //===----------------------------------------------------------------------===// diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index a38d4279cb..0c0cf58076 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -47,9 +47,10 @@ ASTConsumer *CreateGRSimpleVals(Diagnostic &Diags, const std::string& HTMLDir, bool Visualize = false, bool TrimGraph = false); -ASTConsumer* CreateCFRefChecker(Diagnostic &Diags, - const std::string& FunctionName, - const std::string& HTMLDir); +ASTConsumer *CreateCFRefChecker(Diagnostic &Diags, + const std::string& Function, + const std::string& HTMLDir, + bool Visualize = false, bool TrimGraph = false); ASTConsumer *CreateCodeRewriterTest(const std::string& InFile, const std::string& OutFile, diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 6c82f19572..4c8a3525c8 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -122,11 +122,9 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore, "Flag warnings of stores to dead variables."), clEnumValN(WarnUninitVals, "warn-uninit-values", "Flag warnings of uses of unitialized variables."), - clEnumValN(AnalysisGRSimpleVals, "grsimple", + clEnumValN(AnalysisGRSimpleVals, "checker-simple", "Perform path-sensitive constant propagation."), - clEnumValN(AnalysisGRSimpleValsView, "grsimple-view", - "View results of path-sensitive constant propagation."), - clEnumValN(CheckerCFRef, "check-cfref", + clEnumValN(CheckerCFRef, "checker-cfref", "Run the Core Foundation reference count checker."), clEnumValN(TestSerialization, "test-pickling", "Run prototype serialization code."), @@ -153,6 +151,10 @@ static llvm::cl::opt<bool> VerifyDiagnostics("verify", llvm::cl::desc("Verify emitted diagnostics and warnings.")); +static llvm::cl::opt<bool> +VisualizeEG("visualize-egraph", + llvm::cl::desc("Display static analysis Exploded Graph.")); + static llvm::cl::opt<std::string> HTMLDiag("html-diags", llvm::cl::desc("Generate HTML to report diagnostics"), @@ -480,10 +482,9 @@ AnalyzeSpecificFunction("analyze-function", llvm::cl::desc("Run analysis on specific function.")); static llvm::cl::opt<bool> -TrimGraph("trim-path-graph", +TrimGraph("trim-egraph", llvm::cl::desc("Only show error-related paths in the analysis graph.")); - //===----------------------------------------------------------------------===// // Target Triple Processing. //===----------------------------------------------------------------------===// @@ -1052,14 +1053,12 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile, return CreateUnitValsChecker(Diag); case AnalysisGRSimpleVals: - return CreateGRSimpleVals(Diag, AnalyzeSpecificFunction, OutputFile); - - case AnalysisGRSimpleValsView: return CreateGRSimpleVals(Diag, AnalyzeSpecificFunction, OutputFile, - true, TrimGraph); + VisualizeEG, TrimGraph); case CheckerCFRef: - return CreateCFRefChecker(Diag, AnalyzeSpecificFunction, OutputFile); + return CreateCFRefChecker(Diag, AnalyzeSpecificFunction, OutputFile, + VisualizeEG, TrimGraph); case TestSerialization: return CreateSerializationTest(Diag, FileMgr, LangOpts); diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index 00fb06efe5..96fd5884e9 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -22,19 +22,16 @@ class Decl; class Diagnostic; class ASTContext; class PathDiagnosticClient; +class GRTransferFuncs; void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags); void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, bool FullUninitTaint=false); -void CheckCFRefCount(CFG& cfg, Decl& CodeDecl, ASTContext& Ctx, - Diagnostic& Diag, PathDiagnosticClient* PD); +GRTransferFuncs* MakeGRSimpleValsTF(); +GRTransferFuncs* MakeCFRefCountTF(); -unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx, - Diagnostic& Diag, PathDiagnosticClient* PD, - bool Visualize, bool TrimGraph); - } // end namespace clang #endif diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index efd48218e4..85c8e86500 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -874,22 +874,7 @@ void BadRelease::EmitWarnings(BugReporter& BR) { } //===----------------------------------------------------------------------===// -// Driver for the CFRefCount Checker. +// Transfer function creation for external clients. //===----------------------------------------------------------------------===// -namespace clang { - -void CheckCFRefCount(CFG& cfg, Decl& CD, ASTContext& Ctx, - Diagnostic& Diag, PathDiagnosticClient* PD) { - - if (Diag.hasErrorOccurred()) - return; - - GRExprEngine Eng(cfg, CD, Ctx); - CFRefCount TF; - Eng.setTransferFunctions(TF); - Eng.ExecuteWorkList(); - Eng.EmitWarnings(Diag, PD); -} - -} // end clang namespace +GRTransferFuncs* clang::MakeCFRefCountTF() { return new CFRefCount(); } diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 960476dff0..c350ab9752 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -19,6 +19,7 @@ #include "clang/Analysis/PathDiagnostic.h" #include "clang/Analysis/PathSensitive/ValueState.h" #include "clang/Analysis/PathSensitive/BugReporter.h" +#include "clang/Analysis/LocalCheckers.h" #include "llvm/Support/Compiler.h" #include <sstream> @@ -310,36 +311,10 @@ void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) { } //===----------------------------------------------------------------------===// -// Analysis Driver. +// Transfer Function creation for External clients. //===----------------------------------------------------------------------===// -namespace clang { - -unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx, - Diagnostic& Diag, PathDiagnosticClient* PD, - bool Visualize, bool TrimGraph) { - - // Construct the analysis engine. - GRExprEngine Eng(cfg, CD, Ctx); - - // Set base transfer functions. - GRSimpleVals GRSV; - Eng.setTransferFunctions(GRSV); - - // Execute the worklist algorithm. - Eng.ExecuteWorkList(); - - // Display warnings. - Eng.EmitWarnings(Diag, PD); - -#ifndef NDEBUG - if (Visualize) Eng.ViewGraph(TrimGraph); -#endif - - return Eng.getGraph().size(); -} - -} // end clang namespace +GRTransferFuncs* clang::MakeGRSimpleValsTF() { return new GRSimpleVals(); } //===----------------------------------------------------------------------===// // Transfer function for Casts. diff --git a/test/Analysis-Apple/NSString.m b/test/Analysis-Apple/NSString.m index d562a2b967..7662766eb2 100644 --- a/test/Analysis-Apple/NSString.m +++ b/test/Analysis-Apple/NSString.m @@ -1,4 +1,4 @@ -// RUN: clang -grsimple -verify %s +// RUN: clang -checker-simple -verify %s #include <Foundation/NSString.h> #include <Foundation/NSObjCRuntime.h> diff --git a/test/Analysis-Apple/uninit-msg-expr.m b/test/Analysis-Apple/uninit-msg-expr.m index 9ce458925c..b7ff7902b0 100644 --- a/test/Analysis-Apple/uninit-msg-expr.m +++ b/test/Analysis-Apple/uninit-msg-expr.m @@ -1,4 +1,4 @@ -// RUN: clang -grsimple -verify %s +// RUN: clang -checker-simple -verify %s #include <Foundation/NSString.h> #include <Foundation/NSArray.h> diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index c0a26063d7..c73a0384fc 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -1,4 +1,4 @@ -// RUN: clang -grsimple -verify %s +// RUN: clang -checker-simple -verify %s void f1(int *p) { if (p) *p = 1; diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c index 55c542cebf..c59df0904d 100644 --- a/test/Analysis/stack-addr-ps.c +++ b/test/Analysis/stack-addr-ps.c @@ -1,4 +1,4 @@ -// RUN: clang -grsimple -verify %s +// RUN: clang -checker-simple -verify %s int* f1() { int x = 0; |