diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
commit | bb1e3bc1e0be2b8f891db46457a8943451bf4d8b (patch) | |
tree | 1e68501209c9133fbda8d45171e59f8d6f12dd55 /include/clang/Analysis | |
parent | 77212133072dc40f070a280af8217032f55a9eb4 (diff) | |
download | FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.zip FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.tar.gz |
Updaet clang to 92395.
Diffstat (limited to 'include/clang/Analysis')
26 files changed, 293 insertions, 162 deletions
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 0077a85..44ab080 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -70,7 +70,7 @@ public: LiveVariables(AnalysisContext &AC); - /// IsLive - Return true if a variable is live at beginning of a + /// IsLive - Return true if a variable is live at the end of a /// specified block. bool isLive(const CFGBlock* B, const VarDecl* D) const; diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 8a967c3..2b367b7 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -35,7 +35,7 @@ public: struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} - virtual ~AnalysisDataTy() {}; + virtual ~AnalysisDataTy() {} ObserverTy* Observer; bool FullUninitTaint; diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index e6f4cf9..38d4bdf 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -15,8 +15,10 @@ #ifndef LLVM_CLANG_CFG_H #define LLVM_CLANG_CFG_H +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "clang/Analysis/Support/BumpVector.h" #include <cassert> @@ -31,6 +33,17 @@ namespace clang { class LangOptions; class ASTContext; +/// CFGElement - Represents a top-level expression in a basic block. +class CFGElement { + llvm::PointerIntPair<Stmt *, 1> Data; +public: + explicit CFGElement() {} + CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {} + Stmt *getStmt() const { return Data.getPointer(); } + bool asLValue() const { return Data.getInt() == 1; } + operator Stmt*() const { return getStmt(); } +}; + /// CFGBlock - Represents a single basic block in a source-level CFG. /// It consists of: /// @@ -57,7 +70,7 @@ namespace clang { /// class CFGBlock { class StatementList { - typedef BumpVector<Stmt*> ImplTy; + typedef BumpVector<CFGElement> ImplTy; ImplTy Impl; public: StatementList(BumpVectorContext &C) : Impl(C, 4) {} @@ -67,9 +80,9 @@ class CFGBlock { typedef ImplTy::iterator reverse_iterator; typedef ImplTy::const_iterator const_reverse_iterator; - void push_back(Stmt *s, BumpVectorContext &C) { Impl.push_back(s, C); } - Stmt *front() const { return Impl.back(); } - Stmt *back() const { return Impl.front(); } + void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + CFGElement front() const { return Impl.back(); } + CFGElement back() const { return Impl.front(); } iterator begin() { return Impl.rbegin(); } iterator end() { return Impl.rend(); } @@ -80,7 +93,7 @@ class CFGBlock { const_reverse_iterator rbegin() const { return Impl.begin(); } const_reverse_iterator rend() const { return Impl.end(); } - Stmt* operator[](size_t i) const { + CFGElement operator[](size_t i) const { assert(i < Impl.size()); return Impl[Impl.size() - 1 - i]; } @@ -121,7 +134,7 @@ public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C) : Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), BlockID(blockid), Preds(C, 1), Succs(C, 1) {} - ~CFGBlock() {}; + ~CFGBlock() {} // Statement iterators typedef StatementList::iterator iterator; @@ -129,8 +142,8 @@ public: typedef StatementList::reverse_iterator reverse_iterator; typedef StatementList::const_reverse_iterator const_reverse_iterator; - Stmt* front() const { return Stmts.front(); } - Stmt* back() const { return Stmts.back(); } + CFGElement front() const { return Stmts.front(); } + CFGElement back() const { return Stmts.back(); } iterator begin() { return Stmts.begin(); } iterator end() { return Stmts.end(); } @@ -145,8 +158,7 @@ public: unsigned size() const { return Stmts.size(); } bool empty() const { return Stmts.empty(); } - Stmt* operator[](size_t i) const { return Stmts[i]; } - + CFGElement operator[](size_t i) const { return Stmts[i]; } // CFG iterators typedef AdjacentBlocks::iterator pred_iterator; @@ -221,8 +233,8 @@ public: Succs.push_back(Block, C); } - void appendStmt(Stmt* Statement, BumpVectorContext &C) { - Stmts.push_back(Statement, C); + void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) { + Stmts.push_back(CFGElement(Statement, asLValue), C); } }; @@ -333,7 +345,7 @@ public: //===--------------------------------------------------------------------===// CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), - BlkExprMap(NULL), Blocks(BlkBVC, 10) {}; + BlkExprMap(NULL), Blocks(BlkBVC, 10) {} ~CFG(); @@ -370,13 +382,25 @@ private: namespace llvm { +/// Implement simplify_type for CFGElement, so that we can dyn_cast from +/// CFGElement to a specific Stmt class. +template <> struct simplify_type<const ::clang::CFGElement> { + typedef ::clang::Stmt* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) { + return Val.getStmt(); + } +}; + +template <> struct simplify_type< ::clang::CFGElement> + : public simplify_type<const ::clang::CFGElement> {}; + // Traits for: CFGBlock -template <> struct GraphTraits<clang::CFGBlock* > { - typedef clang::CFGBlock NodeType; - typedef clang::CFGBlock::succ_iterator ChildIteratorType; +template <> struct GraphTraits< ::clang::CFGBlock* > { + typedef ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; - static NodeType* getEntryNode(clang::CFGBlock* BB) + static NodeType* getEntryNode(::clang::CFGBlock* BB) { return BB; } static inline ChildIteratorType child_begin(NodeType* N) @@ -386,9 +410,9 @@ template <> struct GraphTraits<clang::CFGBlock* > { { return N->succ_end(); } }; -template <> struct GraphTraits<const clang::CFGBlock* > { - typedef const clang::CFGBlock NodeType; - typedef clang::CFGBlock::const_succ_iterator ChildIteratorType; +template <> struct GraphTraits< const ::clang::CFGBlock* > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; static NodeType* getEntryNode(const clang::CFGBlock* BB) { return BB; } @@ -400,11 +424,11 @@ template <> struct GraphTraits<const clang::CFGBlock* > { { return N->succ_end(); } }; -template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > { - typedef const clang::CFGBlock NodeType; - typedef clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; - static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G) + static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G) { return G.Graph; } static inline ChildIteratorType child_begin(NodeType* N) @@ -416,36 +440,40 @@ template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > { // Traits for: CFG -template <> struct GraphTraits<clang::CFG* > - : public GraphTraits<clang::CFGBlock* > { +template <> struct GraphTraits< ::clang::CFG* > + : public GraphTraits< ::clang::CFGBlock* > { - typedef clang::CFG::iterator nodes_iterator; + typedef ::clang::CFG::iterator nodes_iterator; - static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); } - static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); } - static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); } + static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); } + static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); } }; -template <> struct GraphTraits< const clang::CFG* > - : public GraphTraits< const clang::CFGBlock* > { +template <> struct GraphTraits<const ::clang::CFG* > + : public GraphTraits<const ::clang::CFGBlock* > { - typedef clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_iterator nodes_iterator; - static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); } - static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); } - static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode( const ::clang::CFG* F) { + return &F->getEntry(); + } + static nodes_iterator nodes_begin( const ::clang::CFG* F) { + return F->begin(); + } + static nodes_iterator nodes_end( const ::clang::CFG* F) { + return F->end(); + } }; -template <> struct GraphTraits<Inverse<const clang::CFG*> > - : public GraphTraits<Inverse<const clang::CFGBlock*> > { +template <> struct GraphTraits<Inverse<const ::clang::CFG*> > + : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_iterator nodes_iterator; - static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); } - static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();} - static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();} + static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); } }; - } // end llvm namespace - #endif diff --git a/include/clang/Analysis/FlowSensitive/DataflowValues.h b/include/clang/Analysis/FlowSensitive/DataflowValues.h index 648fe33..7aa15c5 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowValues.h +++ b/include/clang/Analysis/FlowSensitive/DataflowValues.h @@ -79,7 +79,7 @@ public: /// InitializeValues - Invoked by the solver to initialize state needed for /// dataflow analysis. This method is usually specialized by subclasses. - void InitializeValues(const CFG& cfg) {}; + void InitializeValues(const CFG& cfg) {} /// getEdgeData - Retrieves the dataflow values associated with a diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index 8c70e4f..9c343e0 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -56,6 +56,8 @@ void RegisterExperimentalInternalChecks(GRExprEngine &Eng); void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR); void CheckSizeofPointer(const Decl *D, BugReporter &BR); + +void RegisterCallInliner(GRExprEngine &Eng); } // end namespace clang #endif diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index 970b523..d380c45 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -37,7 +37,7 @@ class PathDiagnosticClient : public DiagnosticClient { public: PathDiagnosticClient() {} - virtual ~PathDiagnosticClient() {}; + virtual ~PathDiagnosticClient() {} virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0; diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index abc33b7..63ba558 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -27,6 +27,7 @@ namespace clang { class Decl; class Stmt; class CFG; +class CFGBlock; class LiveVariables; class ParentMap; class ImplicitParamDecl; @@ -136,23 +137,38 @@ public: }; class StackFrameContext : public LocationContext { + // The callsite where this stack frame is established. const Stmt *CallSite; + // The parent block of the callsite. + const CFGBlock *Block; + + // The index of the callsite in the CFGBlock. + unsigned Index; + friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s) - : LocationContext(StackFrame, ctx, parent), CallSite(s) {} + const Stmt *s, const CFGBlock *blk, unsigned idx) + : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), + Index(idx) {} public: ~StackFrameContext() {} const Stmt *getCallSite() const { return CallSite; } + const CFGBlock *getCallSiteBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s) { + const LocationContext *parent, const Stmt *s, + const CFGBlock *blk, unsigned idx) { ProfileCommon(ID, StackFrame, ctx, parent, s); + ID.AddPointer(blk); + ID.AddInteger(idx); } static bool classof(const LocationContext* Ctx) { @@ -230,7 +246,8 @@ public: const StackFrameContext *getStackFrame(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s); + const Stmt *s, const CFGBlock *blk, + unsigned idx); const ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 9ef5cce..8288864 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -73,7 +73,7 @@ public: StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; - }; + } ConstraintManagerCreator getConstraintManagerCreator() { return CreateConstraintMgr; @@ -132,14 +132,15 @@ public: // Get the top level stack frame. const StackFrameContext *getStackFrame(Decl const *D) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0); + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0); } // Get a stack frame with parent. StackFrameContext const *getStackFrame(Decl const *D, LocationContext const *Parent, - Stmt const *S) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S); + Stmt const *S, const CFGBlock *Blk, + unsigned Idx) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx); } }; diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 58c8018..ccebf01 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -203,7 +203,10 @@ public: ~RangedBugReport(); // FIXME: Move this out of line. - void addRange(SourceRange R) { Ranges.push_back(R); } + void addRange(SourceRange R) { + assert(R.isValid()); + Ranges.push_back(R); + } // FIXME: Move this out of line. void getRanges(const SourceRange*& beg, const SourceRange*& end) { diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index a625a7a..924a8b1 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -61,8 +61,12 @@ public: return Eng; } + AnalysisManager &getAnalysisManager() { + return Eng.getAnalysisManager(); + } + ConstraintManager &getConstraintManager() { - return Eng.getConstraintManager(); + return Eng.getConstraintManager(); } StoreManager &getStoreManager() { @@ -265,6 +269,11 @@ public: virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { return false; } + + virtual const GRState *EvalAssume(const GRState *state, SVal Cond, + bool Assumption) { + return state; + } }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index 4144d1a..7ec27ef 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -12,24 +12,27 @@ //===---------------------------------------------------------------------===// #ifndef PREVISIT -#define PREVISIT(NODE) +#define PREVISIT(NODE, FALLBACK) #endif #ifndef POSTVISIT -#define POSTVISIT(NODE) +#define POSTVISIT(NODE, FALLBACK) #endif -PREVISIT(ArraySubscriptExpr) -PREVISIT(BinaryOperator) -PREVISIT(CallExpr) -PREVISIT(CastExpr) -PREVISIT(DeclStmt) -PREVISIT(ObjCMessageExpr) -PREVISIT(ReturnStmt) +PREVISIT(ArraySubscriptExpr, Stmt) +PREVISIT(BinaryOperator, Stmt) +PREVISIT(CallExpr, Stmt) +PREVISIT(CastExpr, Stmt) +PREVISIT(CXXOperatorCallExpr, CallExpr) +PREVISIT(DeclStmt, Stmt) +PREVISIT(ObjCMessageExpr, Stmt) +PREVISIT(ReturnStmt, Stmt) -POSTVISIT(CallExpr) -POSTVISIT(BlockExpr) -POSTVISIT(BinaryOperator) +POSTVISIT(BlockExpr, Stmt) +POSTVISIT(BinaryOperator, Stmt) +POSTVISIT(CallExpr, Stmt) +POSTVISIT(CXXOperatorCallExpr, CallExpr) +POSTVISIT(ObjCMessageExpr, Stmt) #undef PREVISIT #undef POSTVISIT diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h index 7cef17e..f5145bb 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h @@ -53,20 +53,20 @@ public: static_cast<const BinaryOperator*>(S)); break; -#define PREVISIT(NAME) \ +#define PREVISIT(NAME, FALLBACK) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ break; #include "clang/Analysis/PathSensitive/CheckerVisitor.def" } } - + void PostVisit(CheckerContext &C, const Stmt *S) { switch (S->getStmtClass()) { default: assert(false && "Unsupport statement."); return; -#define POSTVISIT(NAME) \ +#define POSTVISIT(NAME, FALLBACK) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->\ PostVisit ## NAME(C,static_cast<const NAME*>(S));\ @@ -75,12 +75,19 @@ break; } } -#define PREVISIT(NAME) \ -void PreVisit ## NAME(CheckerContext &C, const NAME* S) {} + void PreVisitStmt(CheckerContext &C, const Stmt *S) {} + void PostVisitStmt(CheckerContext &C, const Stmt *S) {} + +#define PREVISIT(NAME, FALLBACK) \ +void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ + PreVisit ## FALLBACK(C, S);\ +} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" -#define POSTVISIT(NAME) \ -void PostVisit ## NAME(CheckerContext &C, const NAME* S) {} +#define POSTVISIT(NAME, FALLBACK) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ + PostVisit ## FALLBACK(C, S);\ +} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" }; diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 76cab1d..fb5e1b8 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -207,7 +207,7 @@ class InterExplodedGraphMap { public: ExplodedNode* getMappedNode(const ExplodedNode* N) const; - InterExplodedGraphMap() {}; + InterExplodedGraphMap() {} virtual ~InterExplodedGraphMap() {} }; diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index b78cc6a..74f7a14 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -75,8 +75,7 @@ class GRCoreEngine { void ProcessEndPath(GREndPathNodeBuilder& Builder); - void ProcessStmt(Stmt* S, GRStmtNodeBuilder& Builder); - + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, GRBlockCounter BC); @@ -212,6 +211,8 @@ public: /// of this builder. CFGBlock* getBlock() const { return &B; } + unsigned getIndex() const { return Idx; } + void setAuditor(GRAuditor* A) { Auditor = A; } const GRState* GetState(ExplodedNode* Pred) const { @@ -402,7 +403,7 @@ public: }; class GREndPathNodeBuilder { - GRCoreEngine& Eng; + GRCoreEngine &Eng; CFGBlock& B; ExplodedNode* Pred; @@ -415,6 +416,8 @@ public: ~GREndPathNodeBuilder(); + GRWorkList &getWorkList() { return *Eng.WList; } + ExplodedNode* getPredecessor() const { return Pred; } GRBlockCounter getBlockCounter() const { diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 8b20a82..e05c624 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -25,6 +25,7 @@ #include "clang/Analysis/PathSensitive/BugReporter.h" #include "clang/AST/Type.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" namespace clang { @@ -79,7 +80,7 @@ class GRExprEngine : public GRSubEngine { typedef llvm::DenseMap<void *, unsigned> CheckerMap; CheckerMap CheckerM; - typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered; + typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; CheckersOrdered Checkers; /// BR - The BugReporter associated with this engine. It is important that @@ -110,10 +111,10 @@ public: GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } /// setTransferFunctions - void setTransferFunctions(GRTransferFuncs* tf); + void setTransferFunctionsAndCheckers(GRTransferFuncs* tf); void setTransferFunctions(GRTransferFuncs& tf) { - setTransferFunctions(&tf); + setTransferFunctionsAndCheckers(&tf); } /// ViewGraph - Visualize the ExplodedGraph created by executing the @@ -149,7 +150,7 @@ public: /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder); + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder); /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue @@ -203,9 +204,10 @@ protected: } public: - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, const GRState* St, - ProgramPoint::Kind K = ProgramPoint::PostStmtKind, - const void *tag = 0); + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind, + const void *tag = 0); protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. @@ -263,15 +265,11 @@ protected: /// VisitCall - Transfer function for function calls. void VisitCall(CallExpr* CE, ExplodedNode* Pred, CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, - ExplodedNodeSet& Dst); - void VisitCallRec(CallExpr* CE, ExplodedNode* Pred, - CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, - ExplodedNodeSet& Dst, const FunctionProtoType *, - unsigned ParamIdx = 0); + ExplodedNodeSet& Dst, bool asLValue); /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + ExplodedNodeSet& Dst, bool asLValue); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, @@ -295,6 +293,11 @@ protected: void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + /// VisitCondInit - Transfer function for handling the initialization + /// of a condition variable in an IfStmt, SwitchStmt, etc. + void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred, + ExplodedNodeSet& Dst); + void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -315,19 +318,24 @@ protected: void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, ExplodedNode* Pred, + void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, + ExplodedNode* Pred, ExplodedNodeSet& Dst, SVal ElementV); /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. - void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME, ObjCMessageExpr::arg_iterator I, ObjCMessageExpr::arg_iterator E, - ExplodedNode* Pred, ExplodedNodeSet& Dst); + ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); - void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, + ExplodedNode* Pred, + ExplodedNodeSet& Dst, + bool asLValue); /// VisitReturnStmt - Transfer function logic for return statements. void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -337,8 +345,11 @@ protected: ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. - void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + ExplodedNodeSet & Dst); /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) @@ -353,9 +364,6 @@ protected: return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X; } - bool EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - public: SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, @@ -365,7 +373,7 @@ public: SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { - return R.isValid() ? SVator.EvalBinOpNN(state, op, L, cast<NonLoc>(R), T) : R; + return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; } SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, @@ -399,15 +407,19 @@ public: // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, - const GRState* St, SVal location, - const void *tag, bool isLoad); - - // FIXME: 'tag' should be removed, and a LocationContext should be used - // instead. void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, const void *tag = 0); +private: + void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, const void *tag, + QualType LoadTy); + + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, + const GRState* St, SVal location, + const void *tag, bool isLoad); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 421ebbf..424b0d7 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -41,6 +41,7 @@ namespace clang { class GRStateManager; class GRTransferFuncs; +class Checker; typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&); typedef StoreManager* (*StoreManagerCreator)(GRStateManager&); @@ -160,6 +161,9 @@ public: SymbolManager &getSymbolManager() const; GRTransferFuncs &getTransferFuncs() const; + std::vector<std::pair<void *, Checker *> >::iterator checker_begin() const; + std::vector<std::pair<void *, Checker *> >::iterator checker_end() const; + //==---------------------------------------------------------------------==// // Constraints on values. //==---------------------------------------------------------------------==// @@ -418,6 +422,9 @@ private: /// for manipulating and creating SVals. GRTransferFuncs* TF; + /// Reference to all checkers in GRExprEngine. + std::vector<std::pair<void *, Checker*> > *Checkers; + public: GRStateManager(ASTContext& Ctx, @@ -441,6 +448,8 @@ public: GRTransferFuncs& getTransferFuncs() { return *TF; } + std::vector<std::pair<void *, Checker *> > &getCheckers() { return *Checkers;} + BasicValueFactory &getBasicVals() { return ValueMgr.getBasicValueFactory(); } @@ -697,6 +706,16 @@ inline GRTransferFuncs &GRState::getTransferFuncs() const { return getStateManager().getTransferFuncs(); } +inline std::vector<std::pair<void *, Checker *> >::iterator +GRState::checker_begin() const { + return getStateManager().getCheckers().begin(); +} + +inline std::vector<std::pair<void *, Checker *> >::iterator +GRState::checker_end() const { + return getStateManager().getCheckers().end(); +} + template<typename T> const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const { return getStateManager().add<T>(this, K, get_context<T>()); diff --git a/include/clang/Analysis/PathSensitive/GRSubEngine.h b/include/clang/Analysis/PathSensitive/GRSubEngine.h index 62e36f9..330742d 100644 --- a/include/clang/Analysis/PathSensitive/GRSubEngine.h +++ b/include/clang/Analysis/PathSensitive/GRSubEngine.h @@ -17,6 +17,7 @@ namespace clang { class Stmt; class CFGBlock; +class CFGElement; class GRState; class GRStateManager; class GRBlockCounter; @@ -37,7 +38,7 @@ public: /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) = 0; + virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 2594618..b058460 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -80,9 +80,6 @@ public: return state; } }; - -GRTransferFuncs *CreateCallInliner(ASTContext &ctx); - } // end clang namespace #endif diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 2fe5ea0..b57cfd7 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -72,8 +72,8 @@ public: VarRegionKind = BEG_DECL_REGIONS, FieldRegionKind, ObjCIvarRegionKind, - ObjCObjectRegionKind, - END_DECL_REGIONS = ObjCObjectRegionKind, + CXXObjectRegionKind, + END_DECL_REGIONS = CXXObjectRegionKind, END_TYPED_REGIONS = END_DECL_REGIONS }; @@ -662,33 +662,6 @@ public: } }; -class ObjCObjectRegion : public DeclRegion { - - friend class MemRegionManager; - - ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg) - : DeclRegion(ivd, sReg, ObjCObjectRegionKind) {} - - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const ObjCInterfaceDecl* ivd, - const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind); - } - -public: - const ObjCInterfaceDecl* getInterface() const { - return cast<ObjCInterfaceDecl>(D); - } - - QualType getValueType(ASTContext& C) const { - return C.getObjCInterfaceType(getInterface()); - } - - static bool classof(const MemRegion* R) { - return R->getKind() == ObjCObjectRegionKind; - } -}; - class ObjCIvarRegion : public DeclRegion { friend class MemRegionManager; @@ -752,6 +725,30 @@ public: } }; +class CXXObjectRegion : public TypedRegion { + friend class MemRegionManager; + + // T - The object type. + QualType T; + + CXXObjectRegion(QualType t, const MemRegion *sReg) + : TypedRegion(sReg, CXXObjectRegionKind), T(t) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + QualType T, const MemRegion *sReg); + +public: + QualType getValueType(ASTContext& C) const { + return T; + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == CXXObjectRegionKind; + } +}; + template<typename RegionTy> const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast<RegionTy>(this)) @@ -865,11 +862,6 @@ public: return getFieldRegion(FR->getDecl(), superRegion); } - /// getObjCObjectRegion - Retrieve or create the memory region associated with - /// the instance of a specified Objective-C class. - const ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, - const MemRegion* superRegion); - /// getObjCIvarRegion - Retrieve or create the memory region associated with /// a specified Objective-c instance variable. 'superRegion' corresponds /// to the containing region (which typically represents the Objective-C @@ -877,6 +869,8 @@ public: const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* superRegion); + const CXXObjectRegion *getCXXObjectRegion(QualType T); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 8b5cf40..9206817 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -58,7 +58,7 @@ protected: public: SVal() : Data(0), Kind(0) {} - ~SVal() {}; + ~SVal() {} /// BufferTy - A temporary buffer to hold a set of SVals. typedef llvm::SmallVector<SVal,5> BufferTy; @@ -244,7 +244,8 @@ public: } static inline bool IsLocType(QualType T) { - return T->isAnyPointerType() || T->isBlockPointerType(); + return T->isAnyPointerType() || T->isBlockPointerType() || + T->isReferenceType(); } }; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 648710f..52d73da 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -103,6 +103,9 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; + // T - the object type. + Loc getThisObject(QualType T); + // FIXME: Make out-of-line. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, const MemRegion *region) { @@ -201,7 +204,7 @@ public: class Visitor { public: - virtual ~Visitor() {}; + virtual ~Visitor() {} virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; }; diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index ef4e069..9cec3c4 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -97,13 +97,6 @@ public: DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R, QualType T = QualType()); - DefinedOrUnknownSVal getRegionValueSymbolValOrUnknown(const MemRegion *R, - QualType T) { - if (SymMgr.canSymbolicate(T)) - return getRegionValueSymbolVal(R, T); - return UnknownVal(); - } - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, const Expr *E, unsigned Count); DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 5abe1ab..332f9d3 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -108,9 +108,13 @@ public: return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); } - Stmt* getFirstStmt() const { + CFGElement getFirstElement() const { const CFGBlock* B = getBlock(); - return B->empty() ? NULL : B->front(); + return B->empty() ? CFGElement() : B->front(); + } + + Stmt *getFirstStmt() const { + return getFirstElement().getStmt(); } static bool classof(const ProgramPoint* Location) { @@ -129,7 +133,7 @@ public: Stmt* getLastStmt() const { const CFGBlock* B = getBlock(); - return B->empty() ? NULL : B->back(); + return B->empty() ? CFGElement() : B->back(); } Stmt* getTerminator() const { diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index afc6361..d627b88 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -20,6 +20,7 @@ #include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #define DISPATCH_CASE(CASE,CLASS) \ case Decl::CASE: \ @@ -55,6 +56,7 @@ public: void VisitDecl(Decl* D) { switch (D->getKind()) { DISPATCH_CASE(Function,FunctionDecl) + DISPATCH_CASE(CXXMethod,CXXMethodDecl) DISPATCH_CASE(Var,VarDecl) DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) DISPATCH_CASE(ImplicitParam,ImplicitParamDecl) @@ -69,6 +71,7 @@ public: DEFAULT_DISPATCH(VarDecl) DEFAULT_DISPATCH(FunctionDecl) + DEFAULT_DISPATCH(CXXMethodDecl) DEFAULT_DISPATCH_VARDECL(ParmVarDecl) DEFAULT_DISPATCH(ImplicitParamDecl) DEFAULT_DISPATCH(EnumConstantDecl) diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h index 83700a3..75a4ac6 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h @@ -25,6 +25,25 @@ public: void VisitStmt(Stmt* S) { static_cast< ImplClass* >(this)->VisitChildren(S); } + + void VisitConditionVariableInit(Stmt *S) { + assert(S == this->getCurrentBlkStmt()); + VarDecl *CondVar = 0; + switch (S->getStmtClass()) { +#define CONDVAR_CASE(CLASS) \ +case Stmt::CLASS ## Class:\ +CondVar = cast<CLASS>(S)->getConditionVariable();\ +break; + CONDVAR_CASE(IfStmt) + CONDVAR_CASE(ForStmt) + CONDVAR_CASE(SwitchStmt) + CONDVAR_CASE(WhileStmt) +#undef CONDVAR_CASE + default: + assert(false && "Infeasible"); + } + static_cast<ImplClass*>(this)->Visit(CondVar->getInit()); + } // Defining operator() allows the visitor to be used as a C++ style functor. void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);} diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 426b9cc..8a85ec1 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -54,6 +54,13 @@ public: else return RetTy(); } + + /// VisitConditionVariableInit - Handle the initialization of condition + /// variables at branches. Valid statements include IfStmt, ForStmt, + /// WhileStmt, and SwitchStmt. + RetTy VisitConditionVariableInit(Stmt *S) { + return RetTy(); + } /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in /// CFGBlocks. Root statements are the statements that appear explicitly in @@ -65,6 +72,11 @@ public: NullifyStmt cleanup(CurrentBlkStmt); switch (S->getStmtClass()) { + case Stmt::IfStmtClass: + case Stmt::ForStmtClass: + case Stmt::WhileStmtClass: + case Stmt::SwitchStmtClass: + return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S); DISPATCH_CASE(StmtExpr) DISPATCH_CASE(ConditionalOperator) |