From 789ea076a845b07c9163095afde00407966b334e Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 17 Sep 2007 17:14:52 +0000 Subject: [PATCH] Removed "ObserverTy" from core DataflowValues types. The observer mechanism can be implemented simply by affixing the Observer to an analysis meta data, so it doesn't need to be a required type. This also permits analyses not to implement an Observer if it doesn't make sense. Changed "DataflowValues::MetaDataTy" to "DataflowValues::AnalysisDataTy" to reflect that the type enscapsulated the data associated with analyzing a given CFG. Changed CFGStmtVisitor::BlockStmt_VisitImplicitControlFlowStmt(Stmt*) to ...VisitImplicitControlFlowExpr(Expr*). The type narrowing is more precise and more useful to clients. Added CFGStmtVisitor::BlockStmt_VisitExpr to reflect the visitation of expressions at the block statement level. This captures all implicit control-flow statements as well as other expressions that are hoisted to the block level (such as conditions for terminators and function calls). This is especially useful for dataflow analysis. llvm-svn: 42034 --- clang/Analysis/DataflowSolver.h | 10 ++--- clang/Analysis/UnintializedValues.cpp | 40 +++++++++++-------- clang/include/clang/Analysis/CFGStmtVisitor.h | 21 +++++++--- .../clang/Analysis/CFGVarDeclVisitor.h | 4 +- clang/include/clang/Analysis/DataflowValues.h | 19 +++++---- .../clang/Analysis/UninitializedValues.h | 29 ++++++-------- 6 files changed, 66 insertions(+), 57 deletions(-) diff --git a/clang/Analysis/DataflowSolver.h b/clang/Analysis/DataflowSolver.h index e2150004bb97..de5f9a3dddd0 100644 --- a/clang/Analysis/DataflowSolver.h +++ b/clang/Analysis/DataflowSolver.h @@ -62,14 +62,13 @@ public: typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag; typedef typename _DFValuesTy::ValTy ValTy; typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy; - typedef typename _DFValuesTy::ObserverTy ObserverTy; //===--------------------------------------------------------------------===// // External interface: constructing and running the solver. //===--------------------------------------------------------------------===// public: - DataflowSolver(DFValuesTy& d, ObserverTy* o = NULL) : D(d), O(o) {} + DataflowSolver(DFValuesTy& d) : D(d) {} ~DataflowSolver() {} /// runOnCFG - Computes dataflow values for all blocks in a CFG. @@ -86,7 +85,7 @@ public: /// only be used for querying the dataflow values within a block with /// and Observer object. void runOnBlock(const CFGBlock* B) { - TransferFuncsTy TF (D.getMetaData(),O); + TransferFuncsTy TF (D.getAnalysisData()); ProcessBlock(B,TF,AnalysisDirTag()); } @@ -106,7 +105,7 @@ private: WorkList.enqueue(&cfg.getEntry()); // Create the state for transfer functions. - TransferFuncsTy TF(D.getMetaData(),O); + TransferFuncsTy TF(D.getAnalysisData()); // Process the worklist until it is empty. while (!WorkList.isEmpty()) { @@ -131,7 +130,7 @@ private: WorkList.enqueue(&cfg.getExit()); // Create the state for transfer functions. - TransferFuncsTy TF(D.getMetaData(),O); + TransferFuncsTy TF(D.getAnalysisData()); // Process the worklist until it is empty. while (!WorkList.isEmpty()) { @@ -213,7 +212,6 @@ private: private: DFValuesTy& D; - ObserverTy* O; }; diff --git a/clang/Analysis/UnintializedValues.cpp b/clang/Analysis/UnintializedValues.cpp index 58e263c12d9b..dd741c1af32a 100644 --- a/clang/Analysis/UnintializedValues.cpp +++ b/clang/Analysis/UnintializedValues.cpp @@ -24,26 +24,30 @@ using namespace clang; namespace { -class RegisterDecls : public CFGVarDeclVisitor { - UninitializedValues::MetaDataTy& M; +class RegisterDeclsAndExprs : public CFGVarDeclVisitor { + UninitializedValues::AnalysisDataTy& AD; public: - RegisterDecls(const CFG& cfg, UninitializedValues::MetaDataTy& m) : - CFGVarDeclVisitor(cfg), M(m) {} + RegisterDeclsAndExprs(const CFG& cfg, UninitializedValues::AnalysisDataTy& ad) + : CFGVarDeclVisitor(cfg), AD(ad) + {} void VisitVarDecl(VarDecl* D) { - if (M.Map.find(D) == M.Map.end()) { - M.Map[D] = M.NumDecls++; - } - } + if (AD.VMap.find(D) == AD.VMap.end()) + AD.VMap[D] = AD.Counter++; + } + + void BlockStmt_VisitExpr(Expr* E) { + if (AD.EMap.find(E) == AD.EMap.end()) + AD.EMap[E] = AD.Counter++; + } }; } // end anonymous namespace void UninitializedValues::InitializeValues(const CFG& cfg) { - RegisterDecls R(cfg,this->getMetaData()); - R.VisitAllDecls(); - - getBlockDataMap()[ &cfg.getEntry() ].resize( getMetaData().NumDecls ); + RegisterDeclsAndExprs R(cfg,this->getAnalysisData()); + R.VisitAllDecls(); + getBlockDataMap()[ &cfg.getEntry() ].resize( getAnalysisData().Counter ); } //===--------------------------------------------------------------------===// @@ -53,15 +57,17 @@ void UninitializedValues::InitializeValues(const CFG& cfg) { namespace { class TransferFuncs : public CFGStmtVisitor { UninitializedValues::ValTy V; - UninitializedValues::MetaDataTy& M; - UninitializedValues::ObserverTy* O; + UninitializedValues::AnalysisDataTy& AD; public: - TransferFuncs(UninitializedValues::MetaDataTy& m, - UninitializedValues::ObserverTy* o) : M(m), O(o) { - V.resize(M.NumDecls); + TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) { + V.resize(AD.Counter); } UninitializedValues::ValTy& getVal() { return V; } + +// bool VisitDeclRefExpr(DeclRefExpr* DR); +// bool VisitBinaryOperator(BinaryOperator* B); +// bool VisitUnaryOperator(UnaryOperator* U); }; } // end anonymous namespace diff --git a/clang/include/clang/Analysis/CFGStmtVisitor.h b/clang/include/clang/Analysis/CFGStmtVisitor.h index 3e72598767dc..86181c8551ad 100644 --- a/clang/include/clang/Analysis/CFGStmtVisitor.h +++ b/clang/include/clang/Analysis/CFGStmtVisitor.h @@ -28,7 +28,8 @@ static_cast(this)->BlockStmt_Visit ## CLASS(static_cast(S)); #define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\ { return\ - static_cast(this)->BlockStmt_VisitImplicitControlFlowStmt(S); } + static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(\ + cast(S)); } template class CFGStmtVisitor : public StmtVisitor { @@ -54,7 +55,11 @@ public: } default: - return static_cast(this)->BlockStmt_VisitStmt(S); + if (isa(S)) + return + static_cast(this)->BlockStmt_VisitExpr(cast(S)); + else + return static_cast(this)->BlockStmt_VisitStmt(S); } } @@ -62,8 +67,12 @@ public: DEFAULT_BLOCKSTMT_VISIT(StmtExpr) DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator) - RetTy BlockStmt_VisitImplicitControlFlowStmt(Stmt* S) { - return static_cast(this)->BlockStmt_VisitStmt(S); + RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { + return static_cast(this)->BlockStmt_VisitExpr(E); + } + + RetTy BlockStmt_VisitExpr(Expr* E) { + return static_cast(this)->BlockStmt_VisitStmt(E); } RetTy BlockStmt_VisitStmt(Stmt* S) { @@ -72,12 +81,12 @@ public: RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) { return - static_cast(this)->BlockStmt_VisitImplicitControlFlowStmt(B); + static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(B); } RetTy BlockStmt_VisitComma(BinaryOperator* B) { return - static_cast(this)->BlockStmt_VisitImplicitControlFlowStmt(B); + static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(B); } //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Analysis/CFGVarDeclVisitor.h b/clang/include/clang/Analysis/CFGVarDeclVisitor.h index 75da32874e2d..7e806dde5ed7 100644 --- a/clang/include/clang/Analysis/CFGVarDeclVisitor.h +++ b/clang/include/clang/Analysis/CFGVarDeclVisitor.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H #define LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H -#include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/CFGStmtVisitor.h" #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" #include "clang/AST/CFG.h" @@ -23,7 +23,7 @@ namespace clang { template -class CFGVarDeclVisitor : public StmtVisitor { +class CFGVarDeclVisitor : public CFGStmtVisitor { const CFG& cfg; public: CFGVarDeclVisitor(const CFG& c) : cfg(c) {} diff --git a/clang/include/clang/Analysis/DataflowValues.h b/clang/include/clang/Analysis/DataflowValues.h index 118c588b4fb0..0b7849bbb0c8 100644 --- a/clang/include/clang/Analysis/DataflowValues.h +++ b/clang/include/clang/Analysis/DataflowValues.h @@ -35,7 +35,7 @@ namespace dataflow { } // end namespace dataflow -template class DataflowValues { @@ -44,10 +44,8 @@ class DataflowValues { //===--------------------------------------------------------------------===// public: - typedef typename TypeClass::ValTy ValTy; - typedef typename TypeClass::MetaDataTy MetaDataTy; - typedef typename TypeClass::ObserverTy ObserverTy; - + typedef typename ValueTypes::ValTy ValTy; + typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy; typedef _AnalysisDirTag AnalysisDirTag; typedef llvm::DenseMap BlockDataMapTy; @@ -101,19 +99,20 @@ public: BlockDataMapTy& getBlockDataMap() { return BlockDataMap; } const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; } - /// getMetaData - Retrieves the meta data associated with a dataflow analysis. + /// getAnalysisData - Retrieves the meta data associated with a + /// dataflow analysis for analyzing a particular CFG. /// This is typically consumed by transfer function code (via the solver). /// This can also be used by subclasses to interpret the dataflow values. - MetaDataTy& getMetaData() { return Meta; } - const MetaDataTy& getMetaData() const { return Meta; } + AnalysisDataTy& getAnalysisData() { return AnalysisData; } + const AnalysisDataTy& getAnalysisData() const { return AnalysisData; } //===--------------------------------------------------------------------===// // Internal data. //===--------------------------------------------------------------------===// protected: - BlockDataMapTy BlockDataMap; - MetaDataTy Meta; + BlockDataMapTy BlockDataMap; + AnalysisDataTy AnalysisData; }; } // end namespace clang diff --git a/clang/include/clang/Analysis/UninitializedValues.h b/clang/include/clang/Analysis/UninitializedValues.h index c7067e035c9d..ba01cb58f01c 100644 --- a/clang/include/clang/Analysis/UninitializedValues.h +++ b/clang/include/clang/Analysis/UninitializedValues.h @@ -21,10 +21,12 @@ namespace clang { class VarDecl; + class Expr; -/// UninitializedValuesTypes - Utility class to wrap type declarations -/// used for defining the UninitializedValues class. -class UninitializedValuesTypes { +/// UninitializedValues_ValueTypes - Utility class to wrap type declarations +/// for dataflow values and dataflow analysis state for the +/// Unitialized Values analysis. +class UninitializedValues_ValueTypes { public: class ValTy { llvm::BitVector BV; @@ -41,26 +43,21 @@ public: void copyValues(ValTy& RHS) { BV = RHS.BV; } }; - struct MetaDataTy { - llvm::DenseMap Map; - unsigned NumDecls; + struct AnalysisDataTy { + llvm::DenseMap VMap; + llvm::DenseMap EMap; + unsigned Counter; - MetaDataTy() : NumDecls(0) {} - }; - - class ObserverTy { - virtual ~ObserverTy(); - virtual void ObserveStmt(Stmt* S, MetaDataTy& M, ValTy& V) {} - virtual void ObserveBlockExit(const CFGBlock* B, MetaDataTy& M, ValTy& V) {} + AnalysisDataTy() : Counter(0) {} }; }; - /// UninitializedValues - Objects of this class encapsulate dataflow analysis /// information regarding what variable declarations in a function are /// potentially unintialized. -class UninitializedValues : public DataflowValues { - +class UninitializedValues : + public DataflowValues { + //===--------------------------------------------------------------------===// // Public interface. //===--------------------------------------------------------------------===//