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 @@ -347,6 +347,13 @@ /// imply that `Val` is true. bool flowConditionImplies(BoolValue &Val) const; + /// Returns the `DeclContext` of the block being analysed, if any. Otherwise, + /// returns null. + const DeclContext *getDeclCtx() { return DeclCtx; } + + /// Sets the `DeclContext` of the block being analysed. + void setDeclCtx(const DeclContext *Ctx) { DeclCtx = Ctx; } + /// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise, /// returns null. const ControlFlowContext *getControlFlowContext(const FunctionDecl *F) { @@ -377,6 +384,9 @@ // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; + // `DeclContext` of the block being analysed if provided. + const DeclContext *DeclCtx = nullptr; + // In a properly initialized `Environment`, `ReturnLoc` should only be null if // its `DeclContext` could not be cast to a `FunctionDecl`. StorageLocation *ReturnLoc = nullptr; 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), ReturnLoc(Other.ReturnLoc), + : DACtx(Other.DACtx), DeclCtx(Other.DeclCtx), ReturnLoc(Other.ReturnLoc), ThisPointeeLoc(Other.ThisPointeeLoc), DeclToLoc(Other.DeclToLoc), ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal), MemberLocToStruct(Other.MemberLocToStruct), @@ -168,9 +168,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()) { @@ -185,7 +187,7 @@ ReturnLoc = &createStorageLocation(ReturnType); } - if (const auto *MethodDecl = dyn_cast(&DeclCtx)) { + if (const auto *MethodDecl = dyn_cast(DeclCtx)) { auto *Parent = MethodDecl->getParent(); assert(Parent != nullptr); if (Parent->isLambda()) @@ -210,6 +212,9 @@ const auto *FuncDecl = Call->getDirectCallee(); assert(FuncDecl != nullptr); + + Env.setDeclCtx(FuncDecl); + // FIXME: In order to allow the callee to reference globals, we probably need // to call `initGlobalVars` here in some way. @@ -252,12 +257,12 @@ void Environment::popCall(const Environment &CalleeEnv) { // We ignore `DACtx` because it's already the same in both. We don't want the - // callee's `ReturnLoc` or `ThisPointeeLoc`. We don't bring back `DeclToLoc` - // and `ExprToLoc` because we want to be able to later analyze the same callee - // in a different context, and `setStorageLocation` requires there to not - // already be a storage location assigned. Conceptually, these maps capture - // information from the local scope, so when popping that scope, we do not - // propagate the maps. + // callee's `DeclCtx`, `ReturnLoc` or `ThisPointeeLoc`. We don't bring back + // `DeclToLoc` and `ExprToLoc` because we want to be able to later analyze the + // same callee in a different context, and `setStorageLocation` requires there + // to not already be a storage location assigned. Conceptually, these maps + // capture information from the local scope, so when popping that scope, we do + // not propagate the maps. this->LocToVal = std::move(CalleeEnv.LocToVal); this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct); this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); @@ -304,11 +309,13 @@ assert(DACtx == Other.DACtx); assert(ReturnLoc == Other.ReturnLoc); assert(ThisPointeeLoc == Other.ThisPointeeLoc); + assert(DeclCtx == Other.DeclCtx); auto Effect = LatticeJoinEffect::Unchanged; Environment JoinedEnv(*DACtx); + JoinedEnv.setDeclCtx(DeclCtx); JoinedEnv.ReturnLoc = ReturnLoc; JoinedEnv.ThisPointeeLoc = ThisPointeeLoc;