From ce0ab9d11cec0a81c4e48645a23fa8eddea926ab Mon Sep 17 00:00:00 2001 From: Martin Braenne Date: Mon, 3 Apr 2023 07:02:48 +0000 Subject: [PATCH] [clang][dataflow][NFC] Share code between Environment ctor and pushCallInternal(). The deduplicated code is moved into initVars(). As an added bonus, pushCallInternal() now also gets the "Add all fields mentioned in default member initializers" behavior, which apparently had been added to the Environment ctor but not pushCallInternal(). Reviewed By: xazax.hun, ymandel Differential Revision: https://reviews.llvm.org/D147326 --- .../Analysis/FlowSensitive/DataflowEnvironment.h | 5 +- .../Analysis/FlowSensitive/DataflowEnvironment.cpp | 75 +++++++++------------- 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 678e5b8..b4ae172 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -460,8 +460,9 @@ private: void pushCallInternal(const FunctionDecl *FuncDecl, ArrayRef Args); - /// Assigns storage locations and values to all variables in `Vars`. - void initVars(llvm::DenseSet Vars); + /// Assigns storage locations and values to all global variables and fields + /// referenced in `FuncDecl`. `FuncDecl` must have a body. + void initFieldsAndGlobals(const FunctionDecl *FuncDecl); // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index e3bde37..fbb8d8a 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -203,7 +203,33 @@ static void getFieldsAndGlobalVars(const Stmt &S, // FIXME: Add support for resetting globals after function calls to enable // the implementation of sound analyses. -void Environment::initVars(llvm::DenseSet Vars) { +void Environment::initFieldsAndGlobals(const FunctionDecl *FuncDecl) { + assert(FuncDecl->getBody() != nullptr); + + llvm::DenseSet Fields; + llvm::DenseSet Vars; + + // Look for global variable and field references in the + // constructor-initializers. + if (const auto *CtorDecl = dyn_cast(FuncDecl)) { + for (const auto *Init : CtorDecl->inits()) { + if (const auto *M = Init->getAnyMember()) + Fields.insert(M); + const Expr *E = Init->getInit(); + assert(E != nullptr); + getFieldsAndGlobalVars(*E, Fields, Vars); + } + // Add all fields mentioned in default member initializers. + for (const FieldDecl *F : CtorDecl->getParent()->fields()) + if (const auto *I = F->getInClassInitializer()) + getFieldsAndGlobalVars(*I, Fields, Vars); + } + getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars); + + // These have to be added before the lines that follow to ensure that + // `create*` work correctly for structs. + DACtx->addModeledFields(Fields); + for (const VarDecl *D : Vars) { if (getStorageLocation(*D, SkipPast::None) != nullptr) continue; @@ -239,31 +265,7 @@ Environment::Environment(DataflowAnalysisContext &DACtx, if (const auto *FuncDecl = dyn_cast(&DeclCtx)) { assert(FuncDecl->getBody() != nullptr); - llvm::DenseSet Fields; - llvm::DenseSet Vars; - - // Look for global variable and field references in the - // constructor-initializers. - if (const auto *CtorDecl = dyn_cast(&DeclCtx)) { - for (const auto *Init : CtorDecl->inits()) { - if (const auto *M = Init->getAnyMember()) - Fields.insert(M); - const Expr *E = Init->getInit(); - assert(E != nullptr); - getFieldsAndGlobalVars(*E, Fields, Vars); - } - // Add all fields mentioned in default member initializers. - for (const FieldDecl *F : CtorDecl->getParent()->fields()) - if (const auto *I = F->getInClassInitializer()) - getFieldsAndGlobalVars(*I, Fields, Vars); - } - getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars); - - // These have to be added before the lines that follow to ensure that - // `create*` work correctly for structs. - DACtx.addModeledFields(Fields); - - initVars(Vars); + initFieldsAndGlobals(FuncDecl); for (const auto *ParamDecl : FuncDecl->parameters()) { assert(ParamDecl != nullptr); @@ -337,26 +339,7 @@ void Environment::pushCallInternal(const FunctionDecl *FuncDecl, ArrayRef Args) { CallStack.push_back(FuncDecl); - // FIXME: Share this code with the constructor, rather than duplicating it. - llvm::DenseSet Fields; - llvm::DenseSet Vars; - // Look for global variable references in the constructor-initializers. - if (const auto *CtorDecl = dyn_cast(FuncDecl)) { - for (const auto *Init : CtorDecl->inits()) { - if (const auto *M = Init->getAnyMember()) - Fields.insert(M); - const Expr *E = Init->getInit(); - assert(E != nullptr); - getFieldsAndGlobalVars(*E, Fields, Vars); - } - } - getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars); - - // These have to be added before the lines that follow to ensure that - // `create*` work correctly for structs. - DACtx->addModeledFields(Fields); - - initVars(Vars); + initFieldsAndGlobals(FuncDecl); const auto *ParamIt = FuncDecl->param_begin(); -- 2.7.4