diff options
-rw-r--r-- | clang/include/clang/Checker/PathSensitive/Environment.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Checker/PathSensitive/GRState.h | 2 | ||||
-rw-r--r-- | clang/lib/Checker/GRCoreEngine.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Checker/GRExprEngine.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Checker/GRState.cpp | 6 | ||||
-rw-r--r-- | clang/test/Analysis/inline3.c | 15 |
6 files changed, 27 insertions, 0 deletions
diff --git a/clang/include/clang/Checker/PathSensitive/Environment.h b/clang/include/clang/Checker/PathSensitive/Environment.h index 0852c31faeb..e7c8319fb72 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 9194ee88a1a..bc2fae57cfd 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 a9347d01641..63ac31d6064 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<StackFrameContext>(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 ad229c7b8fb..d25526e1ede 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 592f930316e..ce7d6e2a838 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<GRState::Printer*>::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 00000000000..3661263b6ba --- /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(); +} |