forked from OSchip/llvm-project
[clang][dataflow] Store DeclContext of block being analysed in Environment if available.
Differential Revision: https://reviews.llvm.org/D131065
This commit is contained in:
parent
286d59ef6f
commit
8a4c40bfe8
|
@ -347,6 +347,13 @@ public:
|
|||
/// 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 @@ private:
|
|||
// `DACtx` is not null and not owned by this object.
|
||||
DataflowAnalysisContext *DACtx;
|
||||
|
||||
// `DeclContext` of the block being analysed if provided.
|
||||
const DeclContext *DeclCtx;
|
||||
|
||||
// In a properly initialized `Environment`, `ReturnLoc` should only be null if
|
||||
// its `DeclContext` could not be cast to a `FunctionDecl`.
|
||||
StorageLocation *ReturnLoc = nullptr;
|
||||
|
|
|
@ -154,7 +154,7 @@ Environment::Environment(DataflowAnalysisContext &DACtx)
|
|||
: 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::operator=(const Environment &Other) {
|
|||
}
|
||||
|
||||
Environment::Environment(DataflowAnalysisContext &DACtx,
|
||||
const DeclContext &DeclCtx)
|
||||
const DeclContext &DeclCtxArg)
|
||||
: Environment(DACtx) {
|
||||
if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
|
||||
setDeclCtx(&DeclCtxArg);
|
||||
|
||||
if (const auto *FuncDecl = dyn_cast<FunctionDecl>(DeclCtx)) {
|
||||
assert(FuncDecl->getBody() != nullptr);
|
||||
initGlobalVars(*FuncDecl->getBody(), *this);
|
||||
for (const auto *ParamDecl : FuncDecl->parameters()) {
|
||||
|
@ -185,7 +187,7 @@ Environment::Environment(DataflowAnalysisContext &DACtx,
|
|||
ReturnLoc = &createStorageLocation(ReturnType);
|
||||
}
|
||||
|
||||
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) {
|
||||
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(DeclCtx)) {
|
||||
auto *Parent = MethodDecl->getParent();
|
||||
assert(Parent != nullptr);
|
||||
if (Parent->isLambda())
|
||||
|
@ -210,6 +212,9 @@ Environment Environment::pushCall(const CallExpr *Call) const {
|
|||
|
||||
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 @@ Environment Environment::pushCall(const CallExpr *Call) const {
|
|||
|
||||
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 @@ LatticeJoinEffect Environment::join(const Environment &Other,
|
|||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue