diff options
Diffstat (limited to 'include/clang/Analysis/PathSensitive')
14 files changed, 171 insertions, 211 deletions
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 66e850a91444..9b58f745f0a5 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H +#include "clang/AST/Stmt.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 488334623b34..18eae9ac9f14 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -37,7 +37,6 @@ class AnalysisManager : public BugReporterData { enum AnalysisScope { ScopeTU, ScopeDecl } AScope; - bool DisplayedFunction; bool VisualizeEGDot; bool VisualizeEGUbi; bool PurgeDead; @@ -62,7 +61,7 @@ public: : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), - AScope(ScopeDecl), DisplayedFunction(!displayProgress), + AScope(ScopeDecl), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), EagerlyAssume(eager), TrimGraph(trim) {} @@ -120,8 +119,6 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } - void DisplayFunction(Decl *D); - CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); } diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 914118cb430d..f4297350ec70 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -81,10 +81,10 @@ public: getOriginalNode(const ExplodedNode* N) = 0; }; - BugReport(BugType& bt, const char* desc, const ExplodedNode *n) + BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n) : BT(bt), Description(desc), EndNode(n) {} - BugReport(BugType& bt, const char* shortDesc, const char* desc, + BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc, const ExplodedNode *n) : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {} @@ -193,11 +193,11 @@ public: class RangedBugReport : public BugReport { std::vector<SourceRange> Ranges; public: - RangedBugReport(BugType& D, const char* description, ExplodedNode *n) + RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) : BugReport(D, description, n) {} - RangedBugReport(BugType& D, const char *shortDescription, - const char *description, ExplodedNode *n) + RangedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) : BugReport(D, shortDescription, description, n) {} ~RangedBugReport(); @@ -229,11 +229,11 @@ private: Creators creators; public: - EnhancedBugReport(BugType& D, const char* description, ExplodedNode *n) + EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) : RangedBugReport(D, description, n) {} - EnhancedBugReport(BugType& D, const char *shortDescription, - const char *description, ExplodedNode *n) + EnhancedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) : RangedBugReport(D, shortDescription, description, n) {} ~EnhancedBugReport() {} diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h index 242b8e9afebe..8303dee49afa 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -23,6 +23,7 @@ class BugReportEquivClass; class BugReporter; class BuiltinBugReport; class BugReporterContext; +class ExplodedNode; class GRExprEngine; class BugType { @@ -59,21 +60,27 @@ public: }; class BuiltinBug : public BugType { - GRExprEngine &Eng; + GRExprEngine *Eng; protected: const std::string desc; public: + BuiltinBug(const char *name, const char *description) + : BugType(name, "Logic error"), Eng(0), desc(description) {} + + BuiltinBug(const char *name) + : BugType(name, "Logic error"), Eng(0), desc(name) {} + BuiltinBug(GRExprEngine *eng, const char* n, const char* d) - : BugType(n, "Logic error"), Eng(*eng), desc(d) {} + : BugType(n, "Logic error"), Eng(eng), desc(d) {} BuiltinBug(GRExprEngine *eng, const char* n) - : BugType(n, "Logic error"), Eng(*eng), desc(n) {} + : BugType(n, "Logic error"), Eng(eng), desc(n) {} const std::string &getDescription() const { return desc; } virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {} - void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); } + void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); } virtual void registerInitialVisitors(BugReporterContext& BRC, const ExplodedNode* N, diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 4fc0a617ecf0..b7ed20fab250 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -39,22 +39,19 @@ class CheckerContext { SaveAndRestore<const void*> OldTag; SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveOr OldHasGen; + const GRState *state; public: - CheckerContext(ExplodedNodeSet &dst, - GRStmtNodeBuilder &builder, - GRExprEngine &eng, - ExplodedNode *pred, - const void *tag, bool preVisit) + CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, + GRExprEngine &eng, ExplodedNode *pred, + const void *tag, ProgramPoint::Kind K, + const GRState *st = 0) : Dst(dst), B(builder), Eng(eng), Pred(pred), - OldSink(B.BuildSinks), OldTag(B.Tag), - OldPointKind(B.PointKind), OldHasGen(B.HasGeneratedNode) { - //assert(Dst.empty()); // This is a fake assertion. - // See GRExprEngine::CheckerVisit(), CurrSet is repeatedly used. - B.Tag = tag; - if (preVisit) - B.PointKind = ProgramPoint::PreStmtKind; - } + OldSink(B.BuildSinks), + OldTag(B.Tag, tag), + OldPointKind(B.PointKind, K), + OldHasGen(B.HasGeneratedNode), + state(st) {} ~CheckerContext() { if (!B.BuildSinks && !B.HasGeneratedNode) @@ -64,10 +61,15 @@ public: ConstraintManager &getConstraintManager() { return Eng.getConstraintManager(); } + + StoreManager &getStoreManager() { + return Eng.getStoreManager(); + } + ExplodedNodeSet &getNodeSet() { return Dst; } GRStmtNodeBuilder &getNodeBuilder() { return B; } ExplodedNode *&getPredecessor() { return Pred; } - const GRState *getState() { return B.GetState(Pred); } + const GRState *getState() { return state ? state : B.GetState(Pred); } ASTContext &getASTContext() { return Eng.getContext(); @@ -76,6 +78,10 @@ public: BugReporter &getBugReporter() { return Eng.getBugReporter(); } + + SourceManager &getSourceManager() { + return getBugReporter().getSourceManager(); + } ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) { return GenerateNode(S, getState(), markAsSink); @@ -104,50 +110,69 @@ class Checker { private: friend class GRExprEngine; + // FIXME: Remove the 'tag' option. void GR_Visit(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, - const Stmt *stmt, + const Stmt *S, ExplodedNode *Pred, void *tag, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); - assert(isPrevisit && "Only previsit supported for now."); - _PreVisit(C, stmt); + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind); + if (isPrevisit) + _PreVisit(C, S); + else + _PostVisit(C, S); } + // FIXME: Remove the 'tag' option. void GR_VisitBind(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *AssignE, const Stmt *StoreE, ExplodedNode *Pred, void *tag, SVal location, SVal val, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind); assert(isPrevisit && "Only previsit supported for now."); PreVisitBind(C, AssignE, StoreE, location, val); } - -public: - virtual ~Checker() {} - virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {} - // This is a previsit which takes a node returns a node. - virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, - GRExprEngine &Eng) { - return Pred; + // FIXME: Remove the 'tag' option. + void GR_VisitLocation(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, + const Stmt *S, + ExplodedNode *Pred, const GRState *state, + SVal location, + void *tag, bool isLoad) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isLoad ? ProgramPoint::PreLoadKind : + ProgramPoint::PreStoreKind, state); + VisitLocation(C, S, location); } - - virtual void PreVisitBind(CheckerContext &C, - const Stmt *AssignE, const Stmt *StoreE, - SVal location, SVal val) {} - virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, - const GRState *state, Stmt *S, - GRExprEngine &Eng) { - return Pred; + void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, + SymbolReaper &SymReaper, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState()); + EvalDeadSymbols(C, S, SymReaper); } +public: + virtual ~Checker() {} + virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} + virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} + virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} + virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, + const Stmt *StoreE, SVal location, SVal val) {} + virtual void EvalDeadSymbols(CheckerContext &C, const Stmt *S, + SymbolReaper &SymReaper) {} + virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) {} }; - } // end clang namespace #endif diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index ff6528dae8f5..090a5d397549 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -11,8 +11,19 @@ // //===---------------------------------------------------------------------===// +#ifdef PREVISIT +PREVISIT(ArraySubscriptExpr) +PREVISIT(BinaryOperator) PREVISIT(CallExpr) +PREVISIT(CastExpr) +PREVISIT(DeclStmt) PREVISIT(ObjCMessageExpr) -PREVISIT(BinaryOperator) - +PREVISIT(ReturnStmt) #undef PREVISIT +#endif + +#ifdef POSTVISIT +POSTVISIT(CallExpr) +#undef POSTVISIT +#endif + diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h index e74f49c9a761..7cef17eb6591 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h @@ -27,8 +27,12 @@ namespace clang { template<typename ImplClass> class CheckerVisitor : public Checker { public: - virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) { - PreVisit(C, stmt); + virtual void _PreVisit(CheckerContext &C, const Stmt *S) { + PreVisit(C, S); + } + + virtual void _PostVisit(CheckerContext &C, const Stmt *S) { + PostVisit(C, S); } void PreVisit(CheckerContext &C, const Stmt *S) { @@ -36,10 +40,19 @@ public: default: assert(false && "Unsupport statement."); return; + + case Stmt::ImplicitCastExprClass: + case Stmt::ExplicitCastExprClass: + case Stmt::CStyleCastExprClass: + static_cast<ImplClass*>(this)->PreVisitCastExpr(C, + static_cast<const CastExpr*>(S)); + break; + case Stmt::CompoundAssignOperatorClass: static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C, static_cast<const BinaryOperator*>(S)); break; + #define PREVISIT(NAME) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ @@ -47,13 +60,30 @@ 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) \ +case Stmt::NAME ## Class:\ +static_cast<ImplClass*>(this)->\ +PostVisit ## NAME(C,static_cast<const NAME*>(S));\ +break; +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" + } + } #define PREVISIT(NAME) \ void PreVisit ## NAME(CheckerContext &C, const NAME* S) {} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" + +#define POSTVISIT(NAME) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {} +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" }; } // end clang namespace #endif - diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h index 688cf641491d..a84183e7f27f 100644 --- a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h +++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h @@ -16,38 +16,16 @@ #ifndef LLVM_CLANG_DEREFCHECKER #define LLVM_CLANG_DEREFCHECKER -#include "clang/Analysis/PathSensitive/Checker.h" -#include "clang/Analysis/PathSensitive/BugType.h" +#include <utility> namespace clang { +class GRExprEngine; class ExplodedNode; -class NullDerefChecker : public Checker { - BuiltinBug *BT; - llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes; - -public: - NullDerefChecker() : BT(0) {} - ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V,GRExprEngine &Eng); - - static void *getTag(); - typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator; - iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); } - iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); } -}; - -class UndefDerefChecker : public Checker { - BuiltinBug *BT; -public: - UndefDerefChecker() : BT(0) {} - - ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, GRExprEngine &Eng); - - static void *getTag(); -}; +std::pair<ExplodedNode * const *, ExplodedNode * const *> +GetImplicitNullDereferences(GRExprEngine &Eng); } // end clang namespace + #endif diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 25e47038d72c..1b6d0bdf9c10 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -111,14 +111,6 @@ public: // was larger than sizeof(void *) (an undefined value). ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit; - /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning - /// the address of a stack variable. - ErrorNodes RetsStackAddr; - - /// RetsUndef - Nodes in the ExplodedGraph that result from returning - /// an undefined value. - ErrorNodes RetsUndef; - /// UndefBranches - Nodes in the ExplodedGraph that result from /// taking a branch based on an undefined value. ErrorNodes UndefBranches; @@ -131,22 +123,10 @@ public: // calling a function with the attribute "noreturn". ErrorNodes NoReturnCalls; - /// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from - /// constructing a zero-sized VLA where the size may be zero. - ErrorNodes ImplicitBadSizedVLA; - - /// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from - /// constructing a zero-sized VLA where the size must be zero. - ErrorNodes ExplicitBadSizedVLA; - /// UndefResults - Nodes in the ExplodedGraph where the operands are defined /// by the result is not. Excludes divide-by-zero errors. ErrorNodes UndefResults; - /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function - /// pointers that are NULL (or other constants) or Undefined. - ErrorNodes BadCalls; - /// UndefReceiver - Nodes in the ExplodedGraph resulting from message /// ObjC message expressions where the receiver is undefined (uninitialized). ErrorNodes UndefReceivers; @@ -156,14 +136,6 @@ public: /// value. UndefArgsTy MsgExprUndefArgs; - /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from - /// out-of-bound memory accesses where the index MAY be out-of-bound. - ErrorNodes ImplicitOOBMemAccesses; - - /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from - /// out-of-bound memory accesses where the index MUST be out-of-bound. - ErrorNodes ExplicitOOBMemAccesses; - public: GRExprEngine(AnalysisManager &mgr); @@ -223,58 +195,10 @@ public: return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); } - bool isRetStackAddr(const ExplodedNode* N) const { - return N->isSink() && RetsStackAddr.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isUndefControlFlow(const ExplodedNode* N) const { - return N->isSink() && UndefBranches.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isUndefStore(const ExplodedNode* N) const { - return N->isSink() && UndefStores.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isImplicitNullDeref(const ExplodedNode* N) const { - return false; - } - - bool isExplicitNullDeref(const ExplodedNode* N) const { - return false; - } - - bool isUndefDeref(const ExplodedNode* N) const { - return false; - } - bool isNoReturnCall(const ExplodedNode* N) const { return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0; } - bool isUndefResult(const ExplodedNode* N) const { - return N->isSink() && UndefResults.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isBadCall(const ExplodedNode* N) const { - return false; - } - - bool isUndefArg(const ExplodedNode* N) const { - return false; - } - - bool isUndefReceiver(const ExplodedNode* N) const { - return N->isSink() && UndefReceivers.count(const_cast<ExplodedNode*>(N)) != 0; - } - - typedef ErrorNodes::iterator ret_stackaddr_iterator; - ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); } - ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); } - - typedef ErrorNodes::iterator ret_undef_iterator; - ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); } - ret_undef_iterator ret_undef_end() { return RetsUndef.end(); } - typedef ErrorNodes::iterator undef_branch_iterator; undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); } undef_branch_iterator undef_branches_end() { return UndefBranches.end(); } @@ -305,10 +229,6 @@ public: undef_result_iterator undef_results_begin() { return UndefResults.begin(); } undef_result_iterator undef_results_end() { return UndefResults.end(); } - typedef ErrorNodes::iterator bad_calls_iterator; - bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); } - bad_calls_iterator bad_calls_end() { return BadCalls.end(); } - typedef UndefArgsTy::iterator undef_arg_iterator; undef_arg_iterator msg_expr_undef_arg_begin() { return MsgExprUndefArgs.begin(); @@ -327,20 +247,6 @@ public: return UndefReceivers.end(); } - typedef ErrorNodes::iterator oob_memacc_iterator; - oob_memacc_iterator implicit_oob_memacc_begin() { - return ImplicitOOBMemAccesses.begin(); - } - oob_memacc_iterator implicit_oob_memacc_end() { - return ImplicitOOBMemAccesses.end(); - } - oob_memacc_iterator explicit_oob_memacc_begin() { - return ExplicitOOBMemAccesses.begin(); - } - oob_memacc_iterator explicit_oob_memacc_end() { - return ExplicitOOBMemAccesses.end(); - } - void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C); void AddCheck(GRSimpleAPICheck* A); @@ -368,10 +274,7 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - void ProcessEndPath(GREndPathNodeBuilder& builder) { - getTF().EvalEndPath(*this, builder); - StateMgr.EndPath(builder.getState()); - } + void ProcessEndPath(GREndPathNodeBuilder& builder); GRStateManager& getStateManager() { return StateMgr; } const GRStateManager& getStateManager() const { return StateMgr; } @@ -516,9 +419,6 @@ protected: void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); - const GRState* CheckDivideZero(Expr* Ex, const GRState* St, ExplodedNode* Pred, - SVal Denom); - /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. @@ -553,15 +453,11 @@ public: } protected: - void EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, ExplodedNode* Pred); - void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { assert (Builder && "GRStmtNodeBuilder must be defined."); getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred); } - void EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* s, ExplodedNode* Pred); - const GRState* MarkBranch(const GRState* St, Stmt* Terminator, bool branchTaken); @@ -573,16 +469,22 @@ protected: bool atDeclInit = false); public: + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, - const GRState* St, SVal location, const void *tag = 0); + const GRState* St, SVal location, const void *tag = 0, + QualType LoadTy = QualType()); - ExplodedNode* EvalLocation(Stmt* Ex, ExplodedNode* Pred, + // 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 = 0); + 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, + ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, const void *tag = 0); }; diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 8678ca9b5b9b..ef0c36c44d9f 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -195,6 +195,9 @@ public: // const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const; + + std::pair<const GRState*, const GRState*> + Assume(DefinedOrUnknownSVal cond) const; const GRState *AssumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, @@ -330,12 +333,6 @@ public: void printStdErr() const; void printDOT(llvm::raw_ostream& Out) const; - - // Tags used for the Generic Data Map. - struct NullDerefTag { - static int TagInt; - typedef const SVal* data_type; - }; }; class GRStateSet { @@ -403,10 +400,6 @@ private: /// Alloc - A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator& Alloc; - /// CurrentStmt - The block-level statement currently being visited. This - /// is set by GRExprEngine. - Stmt* CurrentStmt; - /// TF - Object that represents a bundle of transfer functions /// for manipulating and creating SVals. GRTransferFuncs* TF; @@ -583,6 +576,15 @@ inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond, return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond), Assumption); } + +inline std::pair<const GRState*, const GRState*> +GRState::Assume(DefinedOrUnknownSVal Cond) const { + if (Cond.isUnknown()) + return std::make_pair(this, this); + + return getStateManager().ConstraintMgr->AssumeDual(this, + cast<DefinedSVal>(Cond)); +} inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, DefinedOrUnknownSVal UpperBound, diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Analysis/PathSensitive/GRWorkList.h index 17b83fdf9fdc..857fa316911f 100644 --- a/include/clang/Analysis/PathSensitive/GRWorkList.h +++ b/include/clang/Analysis/PathSensitive/GRWorkList.h @@ -16,16 +16,19 @@ #define LLVM_CLANG_ANALYSIS_GRWORKLIST #include "clang/Analysis/PathSensitive/GRBlockCounter.h" +#include <cstddef> namespace clang { - + +class CFGBlock; +class ExplodedNode; class ExplodedNodeImpl; class GRWorkListUnit { ExplodedNode* Node; GRBlockCounter Counter; CFGBlock* Block; - unsigned BlockIdx; + unsigned BlockIdx; // This is the index of the next statement. public: GRWorkListUnit(ExplodedNode* N, GRBlockCounter C, diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 0e487691a891..06d0d976df01 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -77,6 +77,8 @@ public: const MemRegion *getBaseRegion() const; + const MemRegion *StripCasts() const; + bool hasStackStorage() const; bool hasParametersStorage() const; diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 4ba3c7396822..8b5cf40e29cb 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -96,6 +96,8 @@ public: return getRawKind() > UnknownKind; } + bool isConstant() const; + bool isZeroConstant() const; /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true; @@ -434,7 +436,7 @@ public: return static_cast<MemRegion*>(Data); } - const MemRegion* getBaseRegion() const; + const MemRegion* StripCasts() const; template <typename REGION> const REGION* getRegionAs() const { diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 6ca2e9e9aa68..55fa83d9ecc3 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -102,7 +102,8 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; // FIXME: Make out-of-line. - virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){ + virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, + const MemRegion *region) { return UnknownVal(); } @@ -180,8 +181,7 @@ protected: /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. - SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state, - const TypedRegion *R, QualType castTy); + SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy); }; // FIXME: Do we still need this? |
