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 @@ -460,8 +460,9 @@ 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 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -203,7 +203,33 @@ // 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 @@ 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 @@ 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();