diff --git a/clang/include/clang/Checker/PathSensitive/Environment.h b/clang/include/clang/Checker/PathSensitive/Environment.h index 0852c31faeb6..e7c8319fb72b 100644 --- a/clang/include/clang/Checker/PathSensitive/Environment.h +++ b/clang/include/clang/Checker/PathSensitive/Environment.h @@ -59,11 +59,13 @@ public: SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const; AnalysisContext &getAnalysisContext() const { return *ACtx; } + void setAnalysisContext(AnalysisContext *ctx) { ACtx = ctx; } /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) { E->ExprBindings.Profile(ID); + ID.AddPointer(E->ACtx); } /// Profile - Used to profile the contents of this object for inclusion diff --git a/clang/include/clang/Checker/PathSensitive/GRState.h b/clang/include/clang/Checker/PathSensitive/GRState.h index 9194ee88a1a9..bc2fae57cfdd 100644 --- a/clang/include/clang/Checker/PathSensitive/GRState.h +++ b/clang/include/clang/Checker/PathSensitive/GRState.h @@ -115,6 +115,8 @@ public: return Env.getAnalysisContext(); } + const GRState *setAnalysisContext(AnalysisContext *ctx) const; + /// getEnvironment - Return the environment associated with this state. /// The environment is the mapping from expressions to values. const Environment& getEnvironment() const { return Env; } diff --git a/clang/lib/Checker/GRCoreEngine.cpp b/clang/lib/Checker/GRCoreEngine.cpp index a9347d01641c..63ac31d6064d 100644 --- a/clang/lib/Checker/GRCoreEngine.cpp +++ b/clang/lib/Checker/GRCoreEngine.cpp @@ -682,6 +682,7 @@ void GRCallExitNodeBuilder::GenerateNode(const GRState *state) { // Get the callee's location context. const StackFrameContext *LocCtx = cast(Pred->getLocationContext()); + state = state->setAnalysisContext(LocCtx->getParent()->getAnalysisContext()); PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent()); bool isNew; diff --git a/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp index ad229c7b8fbc..d25526e1ede2 100644 --- a/clang/lib/Checker/GRExprEngine.cpp +++ b/clang/lib/Checker/GRExprEngine.cpp @@ -1309,6 +1309,7 @@ void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) { const GRState *state = B.getState(); state = getStoreManager().EnterStackFrame(state, LocCtx); + state = state->setAnalysisContext(LocCtx->getAnalysisContext()); B.GenerateNode(state, LocCtx); } diff --git a/clang/lib/Checker/GRState.cpp b/clang/lib/Checker/GRState.cpp index 592f930316e1..ce7d6e2a8388 100644 --- a/clang/lib/Checker/GRState.cpp +++ b/clang/lib/Checker/GRState.cpp @@ -23,6 +23,12 @@ using namespace clang; // FIXME: Move this elsewhere. ConstraintManager::~ConstraintManager() {} +const GRState *GRState::setAnalysisContext(AnalysisContext *ctx) const { + GRState NewState = *this; + NewState.Env.setAnalysisContext(ctx); + return StateMgr->getPersistentState(NewState); +} + GRStateManager::~GRStateManager() { for (std::vector::iterator I=Printers.begin(), E=Printers.end(); I!=E; ++I) diff --git a/clang/test/Analysis/inline3.c b/clang/test/Analysis/inline3.c new file mode 100644 index 000000000000..3661263b6bae --- /dev/null +++ b/clang/test/Analysis/inline3.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s + + +// Test when entering f1(), we set the right AnalysisContext to Environment. +// Otherwise, block-level expr '1 && a' would not be block-level. +int a; + +void f1() { + if (1 && a) + return; +} + +void f2() { + f1(); +}