diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -167,6 +167,13 @@ LatticeJoinEffect join(const Environment &Other, Environment::ValueModel &Model); + /// Returns the `DeclCtx` of the block being analysed if provided, otherwise + /// returns nullptr. + const DeclContext *getDeclCtx() { return DeclCtx; } + + /// Sets the `DeclCtx` of the block being analysed. + void setDeclCtx(const DeclContext *Ctx) { DeclCtx = Ctx; } + // FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`, // `getStableStorageLocation`, or something more appropriate. @@ -363,6 +370,9 @@ // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; + // `DeclCtx` of the block being analysed if provided. + const DeclContext *DeclCtx; + // Maps from program declarations and statements to storage locations that are // assigned to them. Unlike the maps in `DataflowAnalysisContext`, these // include only storage locations that are in scope for a particular basic diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -154,7 +154,7 @@ : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} Environment::Environment(const Environment &Other) - : DACtx(Other.DACtx), DeclToLoc(Other.DeclToLoc), + : DACtx(Other.DACtx), DeclCtx(Other.DeclCtx), DeclToLoc(Other.DeclToLoc), ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal), MemberLocToStruct(Other.MemberLocToStruct), FlowConditionToken(&DACtx->forkFlowCondition(*Other.FlowConditionToken)) { @@ -167,9 +167,11 @@ } Environment::Environment(DataflowAnalysisContext &DACtx, - const DeclContext &DeclCtx) + const DeclContext &DeclCtxArg) : Environment(DACtx) { - if (const auto *FuncDecl = dyn_cast(&DeclCtx)) { + setDeclCtx(&DeclCtxArg); + + if (const auto *FuncDecl = dyn_cast(DeclCtx)) { assert(FuncDecl->getBody() != nullptr); initGlobalVars(*FuncDecl->getBody(), *this); for (const auto *ParamDecl : FuncDecl->parameters()) { @@ -181,7 +183,7 @@ } } - if (const auto *MethodDecl = dyn_cast(&DeclCtx)) { + if (const auto *MethodDecl = dyn_cast(DeclCtx)) { auto *Parent = MethodDecl->getParent(); assert(Parent != nullptr); if (Parent->isLambda()) @@ -214,6 +216,8 @@ const auto *FuncDecl = Call->getDirectCallee(); assert(FuncDecl != nullptr); assert(FuncDecl->getBody() != nullptr); + + Env.setDeclCtx(FuncDecl); // FIXME: In order to allow the callee to reference globals, we probably need // to call `initGlobalVars` here in some way. @@ -268,12 +272,14 @@ LatticeJoinEffect Environment::join(const Environment &Other, Environment::ValueModel &Model) { - assert(DACtx == Other.DACtx); + assert(DACtx == Other.DACtx && DeclCtx == Other.DeclCtx); auto Effect = LatticeJoinEffect::Unchanged; Environment JoinedEnv(*DACtx); + JoinedEnv.setDeclCtx(DeclCtx); + JoinedEnv.DeclToLoc = intersectDenseMaps(DeclToLoc, Other.DeclToLoc); if (DeclToLoc.size() != JoinedEnv.DeclToLoc.size()) Effect = LatticeJoinEffect::Changed; diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -534,7 +534,9 @@ auto ExitState = (*BlockToOutputState)[ExitBlock]; assert(ExitState); - Env = ExitState->Env; + auto *Caller = Env.getDeclCtx(); + Env = Environment(ExitState->Env); + Env.setDeclCtx(Caller); } }