diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/AnalysisManager.h | 12 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/BugReporter.h | 14 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/ExplodedGraph.h | 5 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 26 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRState.h | 38 | ||||
-rw-r--r-- | lib/Analysis/AnalysisManager.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/BugReporter.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 133 | ||||
-rw-r--r-- | lib/Analysis/GRState.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/AnalysisConsumer.cpp | 9 |
11 files changed, 123 insertions, 142 deletions
diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 78d77b58a1..97534c8716 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -43,6 +43,14 @@ class AnalysisManager : public BugReporterData { bool VisualizeEGDot; bool VisualizeEGUbi; bool PurgeDead; + + /// EargerlyAssume - A flag indicating how the engine should handle + // expressions such as: 'x = (y != 0)'. When this flag is true then + // the subexpression 'y != 0' will be eagerly assumed to be true or false, + // thus evaluating it to the integers 0 or 1 respectively. The upside + // is that this can increase analysis precision until we have a better way + // to lazily evaluate such logic. The downside is that it eagerly + // bifurcates paths. bool EagerlyAssume; bool TrimGraph; @@ -113,12 +121,12 @@ public: return EntryContext->getLiveVariables(); } - virtual ASTContext &getContext() { + virtual ASTContext &getASTContext() { return Ctx; } virtual SourceManager &getSourceManager() { - return getContext().getSourceManager(); + return getASTContext().getSourceManager(); } virtual Diagnostic &getDiagnostic() { diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 519df66c2c..0997edc6bb 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -280,7 +280,7 @@ public: virtual ~BugReporterData(); virtual Diagnostic& getDiagnostic() = 0; virtual PathDiagnosticClient* getPathDiagnosticClient() = 0; - virtual ASTContext& getContext() = 0; + virtual ASTContext& getASTContext() = 0; virtual SourceManager& getSourceManager() = 0; virtual CFG* getCFG() = 0; virtual ParentMap& getParentMap() = 0; @@ -324,7 +324,7 @@ public: iterator begin() { return BugTypes.begin(); } iterator end() { return BugTypes.end(); } - ASTContext& getContext() { return D.getContext(); } + ASTContext& getContext() { return D.getASTContext(); } SourceManager& getSourceManager() { return D.getSourceManager(); } @@ -457,14 +457,8 @@ public: return BR.getSourceManager(); } - const Decl& getCodeDecl() { - return getStateManager().getCodeDecl(); - } - - const CFG& getCFG() { - return *BR.getCFG(); - } - + const Decl &getCodeDecl(); + const CFG &getCFG(); virtual BugReport::NodeResolver& getNodeResolver() = 0; }; diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 55f64339ad..4ffed8950a 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH #include "clang/Analysis/ProgramPoint.h" +#include "clang/Analysis/PathSensitive/AnalysisContext.h" #include "clang/AST/Decl.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/FoldingSet.h" @@ -114,6 +115,10 @@ public: return getLocation().getLocationContext(); } + const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } + + CFG &getCFG() const { return *getLocationContext()->getCFG(); } + const GRState* getState() const { return State; } diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index b330e01590..fbfcded710 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -41,10 +41,6 @@ class GRExprEngine : public GRSubEngine { /// G - the simulation graph. ExplodedGraph& G; - /// Liveness - live-variables information the ValueDecl* and block-level - /// Expr* in the CFG. Used to prune out dead state. - LiveVariables& Liveness; - /// Builder - The current GRStmtNodeBuilder which is used when building the /// nodes for a given statement. GRStmtNodeBuilder* Builder; @@ -89,15 +85,6 @@ class GRExprEngine : public GRSubEngine { // destructor is called before the rest of the GRExprEngine is destroyed. GRBugReporter BR; - /// EargerlyAssume - A flag indicating how the engine should handle - // expressions such as: 'x = (y != 0)'. When this flag is true then - // the subexpression 'y != 0' will be eagerly assumed to be true or false, - // thus evaluating it to the integers 0 or 1 respectively. The upside - // is that this can increase analysis precision until we have a better way - // to lazily evaluate such logic. The downside is that it eagerly - // bifurcates paths. - const bool EagerlyAssume; - public: typedef llvm::SmallPtrSet<ExplodedNode*,2> ErrorNodes; typedef llvm::DenseMap<ExplodedNode*, Expr*> UndefArgsTy; @@ -202,11 +189,7 @@ public: ErrorNodes ExplicitOOBMemAccesses; public: - GRExprEngine(CFG& cfg, const Decl &CD, ASTContext& Ctx, LiveVariables& L, - AnalysisManager &mgr, - bool purgeDead, bool eagerlyAssume = true, - StoreManagerCreator SMC = CreateBasicStoreManager, - ConstraintManagerCreator CMC = CreateBasicConstraintManager); + GRExprEngine(AnalysisManager &mgr); ~GRExprEngine(); @@ -216,6 +199,8 @@ public: /// getContext - Return the ASTContext associated with this analysis. ASTContext& getContext() const { return G.getContext(); } + + AnalysisManager &getAnalysisManager() const { return AMgr; } SValuator &getSValuator() { return SVator; } @@ -236,11 +221,6 @@ public: void ViewGraph(ExplodedNode** Beg, ExplodedNode** End); - /// getLiveness - Returned computed live-variables information for the - /// analyzed function. - const LiveVariables& getLiveness() const { return Liveness; } - LiveVariables& getLiveness() { return Liveness; } - /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. const GRState* getInitialState(const LocationContext *InitLoc); diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index f5faf51b1a..7425d1f4bc 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -72,13 +72,10 @@ class GRStateManager; /// used as a functional object; that is once it is created and made /// "persistent" in a FoldingSet its values will never change. class GRState : public llvm::FoldingSetNode { -public: - // Typedefs. +public: typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy; typedef llvm::ImmutableMap<void*, void*> GenericDataMap; - typedef GRStateManager ManagerTy; - private: void operator=(const GRState& R) const; @@ -222,7 +219,8 @@ public: const GRState *bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr, bool Invalidate) const; - const GRState *bindExpr(const Stmt* Ex, SVal V, bool Invalidate = true) const; + const GRState *bindExpr(const Stmt* Ex, SVal V, CFG &cfg, + bool Invalidate = true) const; const GRState *bindBlkExpr(const Stmt *Ex, SVal V) const { return bindExpr(Ex, V, true, false); @@ -418,36 +416,22 @@ private: /// is set by GRExprEngine. Stmt* CurrentStmt; - /// cfg - The CFG for the analyzed function/method. - CFG& cfg; - - /// codedecl - The Decl representing the function/method being analyzed. - const Decl& codedecl; - /// TF - Object that represents a bundle of transfer functions /// for manipulating and creating SVals. GRTransferFuncs* TF; - /// Liveness - live-variables information of the ValueDecl* and block-level - /// Expr* in the CFG. Used to get initial store and prune out dead state. - LiveVariables& Liveness; - public: GRStateManager(ASTContext& Ctx, StoreManagerCreator CreateStoreManager, ConstraintManagerCreator CreateConstraintManager, - llvm::BumpPtrAllocator& alloc, CFG& c, - const Decl& cd, LiveVariables& L) - : EnvMgr(alloc), - GDMFactory(alloc), - ValueMgr(alloc, Ctx, *this), - Alloc(alloc), - cfg(c), - codedecl(cd), - Liveness(L) { - StoreMgr.reset((*CreateStoreManager)(*this)); - ConstraintMgr.reset((*CreateConstraintManager)(*this)); + llvm::BumpPtrAllocator& alloc) + : EnvMgr(alloc), + GDMFactory(alloc), + ValueMgr(alloc, Ctx, *this), + Alloc(alloc) { + StoreMgr.reset((*CreateStoreManager)(*this)); + ConstraintMgr.reset((*CreateConstraintManager)(*this)); } ~GRStateManager(); @@ -457,7 +441,6 @@ public: ASTContext &getContext() { return ValueMgr.getContext(); } const ASTContext &getContext() const { return ValueMgr.getContext(); } - const Decl &getCodeDecl() { return codedecl; } GRTransferFuncs& getTransferFuncs() { return *TF; } BasicValueFactory &getBasicVals() { @@ -477,7 +460,6 @@ public: ValueManager &getValueManager() { return ValueMgr; } const ValueManager &getValueManager() const { return ValueMgr; } - LiveVariables& getLiveVariables() { return Liveness; } llvm::BumpPtrAllocator& getAllocator() { return Alloc; } MemRegionManager& getRegionManager() { diff --git a/lib/Analysis/AnalysisManager.cpp b/lib/Analysis/AnalysisManager.cpp index 1b490a327a..b73e86da8e 100644 --- a/lib/Analysis/AnalysisManager.cpp +++ b/lib/Analysis/AnalysisManager.cpp @@ -27,7 +27,7 @@ void AnalysisManager::DisplayFunction() { if (isa<FunctionDecl>(getCodeDecl()) || isa<ObjCMethodDecl>(getCodeDecl())) { const NamedDecl *ND = cast<NamedDecl>(getCodeDecl()); - SourceManager &SM = getContext().getSourceManager(); + SourceManager &SM = getASTContext().getSourceManager(); llvm::errs() << "ANALYZE: " << SM.getPresumedLoc(ND->getLocation()).getFilename() << ' ' << ND->getNameAsString() << '\n'; diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index bda31fa4b7..feffd45d9c 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -36,6 +36,14 @@ BugReporterContext::~BugReporterContext() { if ((*I)->isOwnedByReporterContext()) delete *I; } +const Decl& BugReporterContext::getCodeDecl() { + return *BR.getEngine().getAnalysisManager().getCodeDecl(); +} + +const CFG& BugReporterContext::getCFG() { + return *BR.getEngine().getAnalysisManager().getCFG(); +} + //===----------------------------------------------------------------------===// // Helper routines for walking the ExplodedGraph and fetching statements. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 6d678f1c4f..32ac27f258 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -2900,7 +2900,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, unsigned Count = Builder.getCurrentBlockCount(); ValueManager &ValMgr = Eng.getValueManager(); SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count); - state = state->bindExpr(Ex, X, false); + state = state->bindExpr(Ex, X, Pred->getCFG(), false); } break; @@ -2911,14 +2911,14 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, assert (arg_end >= arg_beg); assert (idx < (unsigned) (arg_end - arg_beg)); SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx)); - state = state->bindExpr(Ex, V, false); + state = state->bindExpr(Ex, V, Pred->getCFG(), false); break; } case RetEffect::ReceiverAlias: { assert (Receiver); SVal V = state->getSValAsScalarOrLoc(Receiver); - state = state->bindExpr(Ex, V, false); + state = state->bindExpr(Ex, V, Pred->getCFG(), false); break; } @@ -2930,7 +2930,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, QualType RetT = GetReturnType(Ex, ValMgr.getContext()); state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(), RetT)); - state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false); + state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), Pred->getCFG(), false); // FIXME: Add a flag to the checker where allocations are assumed to // *not fail. @@ -2953,7 +2953,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, QualType RetT = GetReturnType(Ex, ValMgr.getContext()); state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(), RetT)); - state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false); + state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), Pred->getCFG(), false); break; } } @@ -3184,7 +3184,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, // Any leaks or other errors? if (X.isReturnedOwned() && X.getCount() == 0) { - const Decl *CD = &Eng.getStateManager().getCodeDecl(); + const Decl *CD = Eng.getAnalysisManager().getCodeDecl(); if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) { const RetainSummary &Summ = *Summaries.getMethodSummary(MD); RetEffect RE = Summ.getRetEffect(); @@ -3227,7 +3227,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, } } else if (X.isReturnedNotOwned()) { - const Decl *CD = &Eng.getStateManager().getCodeDecl(); + const Decl *CD = Eng.getAnalysisManager().getCodeDecl(); if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) { const RetainSummary &Summ = *Summaries.getMethodSummary(MD); if (Summ.getRetEffect().isOwned()) { diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 17baca7b65..cfb914842f 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -147,26 +147,20 @@ static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { } -GRExprEngine::GRExprEngine(CFG &cfg, const Decl &CD, ASTContext &Ctx, - LiveVariables &L, AnalysisManager &mgr, - bool purgeDead, bool eagerlyAssume, - StoreManagerCreator SMC, - ConstraintManagerCreator CMC) +GRExprEngine::GRExprEngine(AnalysisManager &mgr) : AMgr(mgr), - CoreEngine(Ctx, *this), + CoreEngine(mgr.getASTContext(), *this), G(CoreEngine.getGraph()), - Liveness(L), Builder(NULL), - StateMgr(G.getContext(), SMC, CMC, G.getAllocator(), cfg, CD, L), + StateMgr(G.getContext(), mgr.getStoreManagerCreator(), + mgr.getConstraintManagerCreator(), G.getAllocator()), SymMgr(StateMgr.getSymbolManager()), ValMgr(StateMgr.getValueManager()), SVator(ValMgr.getSValuator()), CurrentStmt(NULL), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", G.getContext())), - PurgeDead(purgeDead), - BR(mgr, *this), - EagerlyAssume(eagerlyAssume) {} + BR(mgr, *this) {} GRExprEngine::~GRExprEngine() { BR.FlushReports(); @@ -250,7 +244,7 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) { Builder->setAuditor(BatchAuditor.get()); // Create the cleaned state. - SymbolReaper SymReaper(Liveness, SymMgr); + SymbolReaper SymReaper(*AMgr.getLiveVariables(), SymMgr); CleanedState = PurgeDead ? StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt, SymReaper) : EntryNode->getState(); @@ -347,11 +341,12 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { } else if (B->getOpcode() == BinaryOperator::Comma) { const GRState* state = GetState(Pred); - MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS()))); + MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS()), + Pred->getCFG())); break; } - if (EagerlyAssume && (B->isRelationalOp() || B->isEqualityOp())) { + if (AMgr.shouldEagerlyAssume() && (B->isRelationalOp() || B->isEqualityOp())) { ExplodedNodeSet Tmp; VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp); EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S)); @@ -463,7 +458,8 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) { const GRState* state = GetState(Pred); - MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr))); + MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr), + Pred->getCFG())); } else Dst.Add(Pred); @@ -477,7 +473,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { case Stmt::UnaryOperatorClass: { UnaryOperator *U = cast<UnaryOperator>(S); - if (EagerlyAssume && (U->getOpcode() == UnaryOperator::LNot)) { + if (AMgr.shouldEagerlyAssume() && (U->getOpcode() == UnaryOperator::LNot)) { ExplodedNodeSet Tmp; VisitUnaryOperator(U, Pred, Tmp, false); EvalEagerlyAssume(Dst, Tmp, U); @@ -545,7 +541,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, case Stmt::StringLiteralClass: { const GRState* state = GetState(Pred); SVal V = state->getLValue(cast<StringLiteral>(Ex)); - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V)); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG())); return; } @@ -978,7 +974,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred, SVal V = state->getLValue(VD, Pred->getLocationContext()); if (asLValue) - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()), ProgramPoint::PostLValueKind); else EvalLoad(Dst, Ex, Pred, state, V); @@ -988,13 +984,13 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred, assert(!asLValue && "EnumConstantDecl does not have lvalue."); SVal V = ValMgr.makeIntVal(ED->getInitVal()); - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V)); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG())); return; } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) { assert(asLValue); SVal V = ValMgr.getFunctionPointer(FD); - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()), ProgramPoint::PostLValueKind); return; } @@ -1032,7 +1028,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, state->getSVal(Idx)); if (asLValue) - MakeNode(Dst, A, *I2, state->bindExpr(A, V), + MakeNode(Dst, A, *I2, state->bindExpr(A, V, Pred->getCFG()), ProgramPoint::PostLValueKind); else EvalLoad(Dst, A, *I2, state, V); @@ -1064,7 +1060,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, SVal L = state->getLValue(state->getSVal(Base), Field); if (asLValue) - MakeNode(Dst, M, *I, state->bindExpr(M, L), + MakeNode(Dst, M, *I, state->bindExpr(M, L, Pred->getCFG()), ProgramPoint::PostLValueKind); else EvalLoad(Dst, M, *I, state, L); @@ -1148,7 +1144,8 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, if (location.isUnknown()) { // This is important. We must nuke the old binding. - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal()), K, tag); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal(), Pred->getCFG()), + K, tag); } else { SVal V = state->getSVal(cast<Loc>(location), Ex->getType()); @@ -1165,7 +1162,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, // V = EvalCast(V, Ex->getType()); //} - MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), K, tag); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()), K, tag); } } @@ -1387,14 +1384,16 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst, ExplodedNode *predNew = *I2; const GRState *stateNew = predNew->getState(); SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType()); - Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res)); + Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res, + Pred->getCFG())); } } // Were they not equal? if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) { SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType()); - Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res)); + Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res, + Pred->getCFG())); } } @@ -1609,7 +1608,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred, // For __builtin_expect, just return the value of the subexpression. assert (CE->arg_begin() != CE->arg_end()); SVal X = state->getSVal(*(CE->arg_begin())); - MakeNode(Dst, CE, *DI, state->bindExpr(CE, X)); + MakeNode(Dst, CE, *DI, state->bindExpr(CE, X, Pred->getCFG())); continue; } @@ -1625,7 +1624,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred, SVal Extent = state->getSVal(*(CE->arg_begin())); state = getStoreManager().setExtent(state, R, Extent); - MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R))); + MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R), + Pred->getCFG())); continue; } @@ -1698,7 +1698,8 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, // First assume that the condition is true. if (const GRState *stateTrue = state->assume(V, true)) { stateTrue = stateTrue->bindExpr(Ex, - ValMgr.makeIntVal(1U, Ex->getType())); + ValMgr.makeIntVal(1U, Ex->getType()), + Pred->getCFG()); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag, Pred->getLocationContext()), stateTrue, Pred)); @@ -1707,7 +1708,8 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, // Next, assume that the condition is false. if (const GRState *stateFalse = state->assume(V, false)) { stateFalse = stateFalse->bindExpr(Ex, - ValMgr.makeIntVal(0U, Ex->getType())); + ValMgr.makeIntVal(0U, Ex->getType()), + Pred->getCFG()); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag, Pred->getLocationContext()), stateFalse, Pred)); @@ -1736,7 +1738,7 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, SVal location = state->getLValue(Ex->getDecl(), BaseVal); if (asLValue) - MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location)); + MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location, Pred->getCFG())); else EvalLoad(Dst, Ex, *I, state, location); } @@ -1812,11 +1814,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, // Handle the case where the container still has elements. SVal TrueV = ValMgr.makeTruthVal(1); - const GRState *hasElems = state->bindExpr(S, TrueV); + const GRState *hasElems = state->bindExpr(S, TrueV, Pred->getCFG()); // Handle the case where the container has no elements. SVal FalseV = ValMgr.makeTruthVal(0); - const GRState *noElems = state->bindExpr(S, FalseV); + const GRState *noElems = state->bindExpr(S, FalseV, Pred->getCFG()); if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV)) if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) { @@ -1968,7 +1970,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, // of this case unless we have *a lot* more knowledge. // SVal V = ValMgr.makeZeroVal(ME->getType()); - MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V)); + MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V, Pred->getCFG())); return; } } @@ -2105,13 +2107,14 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, Exploded const GRState* state = GetState(N); SVal V = state->getSVal(Ex); const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy); - state = Res.getState()->bindExpr(CastE, Res.getSVal()); + state = Res.getState()->bindExpr(CastE, Res.getSVal(), Pred->getCFG()); MakeNode(Dst, CastE, N, state); } } void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, - ExplodedNode* Pred, ExplodedNodeSet& Dst, + ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue) { InitListExpr* ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens()); ExplodedNodeSet Tmp; @@ -2123,9 +2126,10 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, state = state->bindCompoundLiteral(CL, ILV); if (asLValue) - MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL))); + MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL), + Pred->getCFG())); else - MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV)); + MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV, Pred->getCFG())); } } @@ -2249,7 +2253,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = ValMgr.makeCompoundVal(T, StartVals); - MakeNode(Dst, E, Pred, state->bindExpr(E, V)); + MakeNode(Dst, E, Pred, state->bindExpr(E, V, Pred->getCFG())); return; } @@ -2284,7 +2288,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, SVal V = ValMgr.makeCompoundVal(T, NewVals); // Make final state and node. - MakeNode(Dst, E, *NI, state->bindExpr(E, V)); + MakeNode(Dst, E, *NI, state->bindExpr(E, V, (*NI)->getCFG())); } else { // Still some initializer values to go. Push them onto the worklist. @@ -2303,7 +2307,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, Visit(Init, Pred, Tmp); for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) { state = GetState(*I); - MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init))); + MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init), Pred->getCFG())); } return; } @@ -2344,7 +2348,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, amt = getContext().getTypeAlign(T) / 8; MakeNode(Dst, Ex, Pred, - GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType()))); + GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType()), + Pred->getCFG())); } @@ -2368,7 +2373,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, SVal location = state->getSVal(Ex); if (asLValue) - MakeNode(Dst, U, *I, state->bindExpr(U, location), + MakeNode(Dst, U, *I, state->bindExpr(U, location, (*I)->getCFG()), ProgramPoint::PostLValueKind); else EvalLoad(Dst, U, *I, state, location); @@ -2395,7 +2400,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, // For all other types, UnaryOperator::Real is an identity operation. assert (U->getType() == Ex->getType()); const GRState* state = GetState(*I); - MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex))); + MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex), (*I)->getCFG())); } return; @@ -2419,7 +2424,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, assert (Ex->getType()->isIntegerType()); const GRState* state = GetState(*I); SVal X = ValMgr.makeZeroVal(Ex->getType()); - MakeNode(Dst, U, *I, state->bindExpr(U, X)); + MakeNode(Dst, U, *I, state->bindExpr(U, X, (*I)->getCFG())); } return; @@ -2444,7 +2449,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex))); + MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex), (*I)->getCFG())); } return; @@ -2460,7 +2465,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); SVal V = state->getSVal(Ex); - state = state->bindExpr(U, V); + state = state->bindExpr(U, V, (*I)->getCFG()); MakeNode(Dst, U, *I, state); } @@ -2483,7 +2488,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, SVal V = state->getSVal(Ex); if (V.isUnknownOrUndef()) { - MakeNode(Dst, U, *I, state->bindExpr(U, V)); + MakeNode(Dst, U, *I, state->bindExpr(U, V, (*I)->getCFG())); continue; } @@ -2505,12 +2510,13 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, case UnaryOperator::Not: // FIXME: Do we need to handle promotions? - state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V))); + state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V)), + (*I)->getCFG()); break; case UnaryOperator::Minus: // FIXME: Do we need to handle promotions? - state = state->bindExpr(U, EvalMinus(cast<NonLoc>(V))); + state = state->bindExpr(U, EvalMinus(cast<NonLoc>(V)), (*I)->getCFG()); break; case UnaryOperator::LNot: @@ -2532,7 +2538,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, U->getType()); } - state = state->bindExpr(U, Result); + state = state->bindExpr(U, Result, (*I)->getCFG()); break; } @@ -2567,7 +2573,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, // Propagate unknown and undefined values. if (V2.isUnknownOrUndef()) { - MakeNode(Dst, U, *I2, state->bindExpr(U, V2)); + MakeNode(Dst, U, *I2, state->bindExpr(U, V2, (*I2)->getCFG())); continue; } @@ -2613,7 +2619,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, } } - state = state->bindExpr(U, U->isPostfix() ? V2 : Result); + state = state->bindExpr(U, U->isPostfix() ? V2 : Result, (*I2)->getCFG()); // Perform the store. EvalStore(Dst, U, *I2, state, V1, Result); @@ -2837,8 +2843,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. - EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV), LeftV, - RightV); + EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV, (*I2)->getCFG()), + LeftV, RightV); continue; } @@ -2890,7 +2896,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Otherwise, create a new node. - MakeNode(Dst, B, *I2, state->bindExpr(B, Result)); + MakeNode(Dst, B, *I2, state->bindExpr(B, Result, (*I2)->getCFG())); continue; } } @@ -2938,14 +2944,15 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Propagate undefined values (left-side). if (V.isUndef()) { - EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V), location, V); + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V, (*I3)->getCFG()), + location, V); continue; } // Propagate unknown values (left and right-side). if (RightV.isUnknown() || V.isUnknown()) { - EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal()), - location, UnknownVal()); + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal(), + (*I3)->getCFG()), location, UnknownVal()); continue; } @@ -2972,8 +2979,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Evaluate operands and promote to result type. if (RightV.isUndef()) { // Propagate undefined values (right-side). - EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV), location, - RightV); + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV, (*I3)->getCFG()), + location, RightV); continue; } @@ -3018,8 +3025,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy); } - EvalStore(Dst, |