aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h79
-rw-r--r--include/clang/Analysis/PathSensitive/ExplodedGraph.h14
-rw-r--r--include/clang/Analysis/PathSensitive/GRCoreEngine.h68
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h74
-rw-r--r--include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h4
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h2
6 files changed, 128 insertions, 113 deletions
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index 7ff79fc53d..9f8b17ac00 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -19,9 +19,6 @@
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "llvm/ADT/SmallPtrSet.h"
-// FIXME: ExplodedGraph<> should be templated on state, not the checker engine.
-#include "clang/Analysis/PathSensitive/GRExprEngine.h"
-
namespace clang {
class PathDiagnostic;
@@ -29,61 +26,79 @@ class PathDiagnosticPiece;
class PathDiagnosticClient;
class ASTContext;
class Diagnostic;
-
-class BugDescription {
+class BugReporter;
+class GRExprEngine;
+class ValueState;
+
+class BugType {
public:
- BugDescription() {}
- virtual ~BugDescription() {}
+ BugType() {}
+ virtual ~BugType();
virtual const char* getName() const = 0;
+ virtual const char* getDescription() const { return getName(); }
+
+ virtual void EmitWarnings(BugReporter& BR) {}
+};
- virtual const char* getDescription() const = 0;
+class BugReport {
+ const BugType& Desc;
+
+public:
+ BugReport(const BugType& D) : Desc(D) {}
+ virtual ~BugReport();
+
+ const BugType& getBugType() const { return Desc; }
+
+ const char* getName() const { return getBugType().getName(); }
+ const char* getDescription() const { return getBugType().getDescription(); }
virtual PathDiagnosticPiece* getEndPath(ASTContext& Ctx,
ExplodedNode<ValueState> *N) const;
virtual void getRanges(const SourceRange*& beg,
const SourceRange*& end) const;
-};
-
-class BugReporterHelper {
-public:
- virtual ~BugReporterHelper() {}
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
ExplodedNode<ValueState>* PrevN,
- ExplodedGraph<GRExprEngine>& G,
- ASTContext& Ctx) = 0;
+ ExplodedGraph<ValueState>& G,
+ ASTContext& Ctx);
};
class BugReporter {
llvm::SmallPtrSet<void*,10> CachedErrors;
+ Diagnostic& Diag;
+ PathDiagnosticClient* PD;
+ ASTContext& Ctx;
+ GRExprEngine& Eng;
public:
- BugReporter() {}
+ BugReporter(Diagnostic& diag, PathDiagnosticClient* pd,
+ ASTContext& ctx, GRExprEngine& eng)
+ : Diag(diag), PD(pd), Ctx(ctx), Eng(eng) {}
+
~BugReporter();
- void EmitPathWarning(Diagnostic& Diag, PathDiagnosticClient* PDC,
- ASTContext& Ctx, const BugDescription& B,
- ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N,
- BugReporterHelper** BegHelpers = NULL,
- BugReporterHelper** EndHelpers = NULL);
+ Diagnostic& getDiagnostic() { return Diag; }
+
+ PathDiagnosticClient* getDiagnosticClient() { return PD; }
- void EmitWarning(Diagnostic& Diag, ASTContext& Ctx,
- const BugDescription& B,
- ExplodedNode<ValueState>* N);
+ ASTContext& getContext() { return Ctx; }
+ ExplodedGraph<ValueState>& getGraph();
-private:
+ GRExprEngine& getEngine() { return Eng; }
+
+ void EmitPathWarning(BugReport& R, ExplodedNode<ValueState>* N);
+
+ void EmitWarning(BugReport& R, ExplodedNode<ValueState>* N);
+
+ void clearCache() { CachedErrors.clear(); }
+
bool IsCached(ExplodedNode<ValueState>* N);
- void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
- const BugDescription& B,
- ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N,
- BugReporterHelper** BegHelpers = NULL,
- BugReporterHelper** EndHelpers = NULL);
+ void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R,
+ ExplodedNode<ValueState>* N);
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
index 30d95605ea..8db069639b 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
@@ -278,17 +278,14 @@ public:
};
-template <typename CHECKER>
+template <typename STATE>
class ExplodedGraph : public ExplodedGraphImpl {
public:
- typedef CHECKER CheckerTy;
- typedef typename CHECKER::StateTy StateTy;
+ typedef STATE StateTy;
typedef ExplodedNode<StateTy> NodeTy;
typedef llvm::FoldingSet<NodeTy> AllNodesTy;
protected:
- llvm::OwningPtr<CheckerTy> CheckerState;
-
/// Nodes - The nodes in the graph.
AllNodesTy Nodes;
@@ -305,12 +302,7 @@ protected:
public:
ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
- : ExplodedGraphImpl(c, cd, ctx), CheckerState(new CheckerTy(*this)) {}
-
- /// getCheckerState - Returns the internal checker state associated
- /// with the exploded graph. Ownership remains with the ExplodedGraph
- /// objecct.
- CheckerTy* getCheckerState() const { return CheckerState.get(); }
+ : ExplodedGraphImpl(c, cd, ctx) {}
/// getNode - Retrieve the node associated with a (Location,State) pair,
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
index 35fddadf33..5b7aeb5975 100644
--- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
@@ -111,7 +111,7 @@ protected:
public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkList(unsigned Steps = 1000000);
+ bool ExecuteWorkList(unsigned Steps);
virtual ~GRCoreEngineImpl() {}
@@ -309,11 +309,10 @@ public:
}
};
-template<typename CHECKER>
+template<typename STATE>
class GRBranchNodeBuilder {
- typedef CHECKER CheckerTy;
- typedef typename CheckerTy::StateTy StateTy;
- typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRBranchNodeBuilderImpl& NB;
@@ -392,11 +391,10 @@ public:
inline void* getState() const { return Pred->State; }
};
-template<typename CHECKER>
+template<typename STATE>
class GRIndirectGotoNodeBuilder {
- typedef CHECKER CheckerTy;
- typedef typename CheckerTy::StateTy StateTy;
- typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRIndirectGotoNodeBuilderImpl& NB;
@@ -459,11 +457,10 @@ public:
inline void* getState() const { return Pred->State; }
};
-template<typename CHECKER>
+template<typename STATE>
class GRSwitchNodeBuilder {
- typedef CHECKER CheckerTy;
- typedef typename CheckerTy::StateTy StateTy;
- typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRSwitchNodeBuilderImpl& NB;
@@ -492,21 +489,19 @@ public:
};
-template<typename CHECKER>
+template<typename SUBENGINE>
class GRCoreEngine : public GRCoreEngineImpl {
public:
- typedef CHECKER CheckerTy;
- typedef typename CheckerTy::StateTy StateTy;
- typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef SUBENGINE SubEngineTy;
+ typedef typename SubEngineTy::StateTy StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
protected:
- // A local reference to the checker that avoids an indirect access
- // via the Graph.
- CheckerTy* Checker;
+ SubEngineTy& SubEngine;
virtual void* getInitialState() {
- return getCheckerState().getInitialState();
+ return SubEngine.getInitialState();
}
virtual void* ProcessEOP(CFGBlock* Blk, void* State) {
@@ -516,44 +511,44 @@ protected:
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
GRStmtNodeBuilder<StateTy> Builder(BuilderImpl);
- Checker->ProcessStmt(S, Builder);
+ SubEngine.ProcessStmt(S, Builder);
}
virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
GRBlockCounter BC) {
- return Checker->ProcessBlockEntrance(Blk,
- static_cast<StateTy*>(State), BC);
+ return SubEngine.ProcessBlockEntrance(Blk, static_cast<StateTy*>(State),BC);
}
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& BuilderImpl) {
- GRBranchNodeBuilder<CHECKER> Builder(BuilderImpl);
- Checker->ProcessBranch(Condition, Terminator, Builder);
+ GRBranchNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessBranch(Condition, Terminator, Builder);
}
virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
- GRIndirectGotoNodeBuilder<CHECKER> Builder(BuilderImpl);
- Checker->ProcessIndirectGoto(Builder);
+ GRIndirectGotoNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessIndirectGoto(Builder);
}
virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) {
- GRSwitchNodeBuilder<CHECKER> Builder(BuilderImpl);
- Checker->ProcessSwitch(Builder);
+ GRSwitchNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessSwitch(Builder);
}
public:
/// Construct a GRCoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
- GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx)
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine)
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), GRWorkList::MakeDFS()),
- Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
+ SubEngine(subengine) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
- GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist)
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist,
+ SubEngineTy& subengine)
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), wlist),
- Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
+ SubEngine(subengine) {}
virtual ~GRCoreEngine() {}
@@ -562,11 +557,6 @@ public:
return *static_cast<GraphTy*>(G.get());
}
- /// getCheckerState - Returns the internal checker state.
- CheckerTy& getCheckerState() {
- return *Checker;
- }
-
/// takeGraph - Returns the exploded graph. Ownership of the graph is
/// transfered to the caller.
GraphTy* takeGraph() {
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index e88b377a97..473b658b67 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -21,26 +21,30 @@
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
-namespace clang {
+namespace clang {
- class StatelessChecks;
+ class BugType;
+ class PathDiagnosticClient;
+ class Diagnostic;
class GRExprEngine {
public:
typedef ValueState StateTy;
- typedef ExplodedGraph<GRExprEngine> GraphTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
typedef GraphTy::NodeTy NodeTy;
// Builders.
- typedef GRStmtNodeBuilder<StateTy> StmtNodeBuilder;
- typedef GRBranchNodeBuilder<GRExprEngine> BranchNodeBuilder;
- typedef GRIndirectGotoNodeBuilder<GRExprEngine> IndirectGotoNodeBuilder;
- typedef GRSwitchNodeBuilder<GRExprEngine> SwitchNodeBuilder;
- typedef ExplodedNodeSet<StateTy> NodeSet;
+ typedef GRStmtNodeBuilder<StateTy> StmtNodeBuilder;
+ typedef GRBranchNodeBuilder<StateTy> BranchNodeBuilder;
+ typedef GRIndirectGotoNodeBuilder<StateTy> IndirectGotoNodeBuilder;
+ typedef GRSwitchNodeBuilder<StateTy> SwitchNodeBuilder;
+ typedef ExplodedNodeSet<StateTy> NodeSet;
protected:
+ GRCoreEngine<GRExprEngine> CoreEngine;
+
/// G - the simulation graph.
GraphTy& G;
@@ -62,6 +66,10 @@ protected:
/// for manipulating and creating RVals.
GRTransferFuncs* TF;
+ /// BugTypes - Objects used for reporting bugs.
+ typedef std::vector<BugType*> BugTypeSet;
+ BugTypeSet BugTypes;
+
/// SymMgr - Object that manages the symbol information.
SymbolManager& SymMgr;
@@ -154,18 +162,11 @@ protected:
UndefArgsTy MsgExprUndefArgs;
public:
- GRExprEngine(GraphTy& g) :
- G(g), Liveness(G.getCFG()),
- Builder(NULL),
- StateMgr(G.getContext(), G.getAllocator()),
- BasicVals(StateMgr.getBasicValueFactory()),
- TF(NULL), // FIXME.
- SymMgr(StateMgr.getSymbolManager()),
- StmtEntryNode(NULL), CleanedState(NULL), CurrentStmt(NULL) {
-
- // Compute liveness information.
- Liveness.runOnCFG(G.getCFG());
- Liveness.runOnAllBlocks(G.getCFG(), NULL, true);
+ GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx);
+ ~GRExprEngine();
+
+ void ExecuteWorkList(unsigned Steps = 150000) {
+ CoreEngine.ExecuteWorkList(Steps);
}
/// getContext - Return the ASTContext associated with this analysis.
@@ -175,8 +176,11 @@ public:
CFG& getCFG() { return G.getCFG(); }
/// setTransferFunctions
- void setTransferFunctions(GRTransferFuncs* tf) { TF = tf; }
- void setTransferFunctions(GRTransferFuncs& tf) { TF = &tf; }
+ void setTransferFunctions(GRTransferFuncs* tf);
+
+ void setTransferFunctions(GRTransferFuncs& tf) {
+ setTransferFunctions(&tf);
+ }
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
@@ -188,6 +192,24 @@ public:
/// in the ExplodedGraph.
ValueState* getInitialState();
+ GraphTy& getGraph() { return G; }
+ const GraphTy& getGraph() const { return G; }
+
+ typedef BugTypeSet::iterator bug_type_iterator;
+ typedef BugTypeSet::const_iterator const_bug_type_iterator;
+
+ bug_type_iterator bug_types_begin() { return BugTypes.begin(); }
+ bug_type_iterator bug_types_end() { return BugTypes.end(); }
+
+ const_bug_type_iterator bug_types_begin() const { return BugTypes.begin(); }
+ const_bug_type_iterator bug_types_end() const { return BugTypes.end(); }
+
+ void Register(BugType* B) {
+ BugTypes.push_back(B);
+ }
+
+ void EmitWarnings(Diagnostic& Diag, PathDiagnosticClient* PD);
+
bool isRetStackAddr(const NodeTy* N) const {
return N->isSink() && RetsStackAddr.count(const_cast<NodeTy*>(N)) != 0;
}
@@ -317,13 +339,9 @@ public:
return MsgExprChecks.end();
}
- void AddCallCheck(GRSimpleAPICheck* A) {
- CallChecks.push_back(A);
- }
+ void AddCallCheck(GRSimpleAPICheck* A);
- void AddObjCMessageExprCheck(GRSimpleAPICheck* A) {
- MsgExprChecks.push_back(A);
- }
+ void AddObjCMessageExprCheck(GRSimpleAPICheck* A);
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
diff --git a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h b/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
index 16b23c558c..782ddcfffe 100644
--- a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
+++ b/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
@@ -33,9 +33,7 @@ class GRSimpleAPICheck : public GRAuditor<ValueState> {
public:
GRSimpleAPICheck() {}
virtual ~GRSimpleAPICheck() {}
- virtual void ReportResults(Diagnostic& Diag, PathDiagnosticClient* PD,
- ASTContext& Ctx, BugReporter& BR,
- ExplodedGraph<GRExprEngine>& G) = 0;
+ virtual void EmitWarnings(BugReporter& BR) = 0;
};
} // end namespace clang
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
index 55a0fae273..9c68f20e74 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -32,6 +32,8 @@ public:
return NULL;
}
+ virtual void RegisterChecks(GRExprEngine& Eng) {}
+
// Casts.
virtual RVal EvalCast(GRExprEngine& Engine, NonLVal V, QualType CastT) =0;