Author: Wei Yi Tee Date: 2022-06-27T11:16:51+02:00 New Revision: 12c7352fa4885a61997cff26f9578bacc166df3b
URL: https://github.com/llvm/llvm-project/commit/12c7352fa4885a61997cff26f9578bacc166df3b DIFF: https://github.com/llvm/llvm-project/commit/12c7352fa4885a61997cff26f9578bacc166df3b.diff LOG: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`. `createStorageLocation` in `DataflowEnvironment` is now a trivial wrapper around the logic in `DataflowAnalysisContext`. Additionally, `getObjectFields` and `getFieldsFromClassHierarchy` (required for the implementation of `createStorageLocation`) are also moved to `DataflowAnalysisContext`. Reviewed By: gribozavr2, sgatev Differential Revision: https://reviews.llvm.org/D128359 Added: Modified: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h index 6011584f20064..58acd5639c436 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -44,6 +44,9 @@ namespace dataflow { const Expr &ignoreCFGOmittedNodes(const Expr &E); const Stmt &ignoreCFGOmittedNodes(const Stmt &S); +/// Returns the set of all fields in the type. +llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type); + /// Owns objects that encompass the state of a program and stores context that /// is used during dataflow analysis. class DataflowAnalysisContext { @@ -85,6 +88,19 @@ class DataflowAnalysisContext { return *cast<T>(Vals.back().get()); } + /// Returns a stable storage location appropriate for `Type`. + /// + /// Requirements: + /// + /// `Type` must not be null. + StorageLocation &getStableStorageLocation(QualType Type); + + /// Returns a stable storage location for `D`. + StorageLocation &getStableStorageLocation(const VarDecl &D); + + /// Returns a stable storage location for `E`. + StorageLocation &getStableStorageLocation(const Expr &E); + /// Assigns `Loc` as the storage location of `D`. /// /// Requirements: diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index 475eeef537376..9e4b03e36bb70 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -22,6 +22,39 @@ namespace clang { namespace dataflow { +StorageLocation & +DataflowAnalysisContext::getStableStorageLocation(QualType Type) { + assert(!Type.isNull()); + if (Type->isStructureOrClassType() || Type->isUnionType()) { + // FIXME: Explore options to avoid eager initialization of fields as some of + // them might not be needed for a particular analysis. + llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; + for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())}); + return takeOwnership( + std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique<ScalarStorageLocation>(Type)); +} + +StorageLocation & +DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) { + if (auto *Loc = getStorageLocation(D)) + return *Loc; + auto &Loc = getStableStorageLocation(D.getType()); + setStorageLocation(D, Loc); + return Loc; +} + +StorageLocation & +DataflowAnalysisContext::getStableStorageLocation(const Expr &E) { + if (auto *Loc = getStorageLocation(E)) + return *Loc; + auto &Loc = getStableStorageLocation(E.getType()); + setStorageLocation(E, Loc); + return Loc; +} + static std::pair<BoolValue *, BoolValue *> makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) { auto Res = std::make_pair(&LHS, &RHS); @@ -190,3 +223,27 @@ const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) { return ignoreCFGOmittedNodes(*E); return S; } + +// FIXME: Does not precisely handle non-virtual diamond inheritance. A single +// field decl will be modeled for all instances of the inherited field. +static void +getFieldsFromClassHierarchy(QualType Type, + llvm::DenseSet<const FieldDecl *> &Fields) { + if (Type->isIncompleteType() || Type->isDependentType() || + !Type->isRecordType()) + return; + + for (const FieldDecl *Field : Type->getAsRecordDecl()->fields()) + Fields.insert(Field); + if (auto *CXXRecord = Type->getAsCXXRecordDecl()) + for (const CXXBaseSpecifier &Base : CXXRecord->bases()) + getFieldsFromClassHierarchy(Base.getType(), Fields); +} + +/// Gets the set of all fields in the type. +llvm::DenseSet<const FieldDecl *> +clang::dataflow::getObjectFields(QualType Type) { + llvm::DenseSet<const FieldDecl *> Fields; + getFieldsFromClassHierarchy(Type, Fields); + return Fields; +} diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index e8d3a4e6d4505..7711302ef7b67 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ static void initGlobalVars(const Stmt &S, Environment &Env) { } } -// FIXME: Does not precisely handle non-virtual diamond inheritance. A single -// field decl will be modeled for all instances of the inherited field. -static void -getFieldsFromClassHierarchy(QualType Type, - llvm::DenseSet<const FieldDecl *> &Fields) { - if (Type->isIncompleteType() || Type->isDependentType() || - !Type->isRecordType()) - return; - - for (const FieldDecl *Field : Type->getAsRecordDecl()->fields()) - Fields.insert(Field); - if (auto *CXXRecord = Type->getAsCXXRecordDecl()) - for (const CXXBaseSpecifier &Base : CXXRecord->bases()) - getFieldsFromClassHierarchy(Base.getType(), Fields); -} - -/// Gets the set of all fields in the type. -static llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type) { - llvm::DenseSet<const FieldDecl *> Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,21 @@ LatticeJoinEffect Environment::join(const Environment &Other, } StorageLocation &Environment::createStorageLocation(QualType Type) { - assert(!Type.isNull()); - if (Type->isStructureOrClassType() || Type->isUnionType()) { - // FIXME: Explore options to avoid eager initialization of fields as some of - // them might not be needed for a particular analysis. - llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; - for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); - return takeOwnership( - std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique<ScalarStorageLocation>(Type)); + return DACtx->getStableStorageLocation(Type); } StorageLocation &Environment::createStorageLocation(const VarDecl &D) { // Evaluated declarations are always assigned the same storage locations to // ensure that the environment stabilizes across loop iterations. Storage // locations for evaluated declarations are stored in the analysis context. - if (auto *Loc = DACtx->getStorageLocation(D)) - return *Loc; - auto &Loc = createStorageLocation(D.getType()); - DACtx->setStorageLocation(D, Loc); - return Loc; + return DACtx->getStableStorageLocation(D); } StorageLocation &Environment::createStorageLocation(const Expr &E) { // Evaluated expressions are always assigned the same storage locations to // ensure that the environment stabilizes across loop iterations. Storage // locations for evaluated expressions are stored in the analysis context. - if (auto *Loc = DACtx->getStorageLocation(E)) - return *Loc; - auto &Loc = createStorageLocation(E.getType()); - DACtx->setStorageLocation(E, Loc); - return Loc; + return DACtx->getStableStorageLocation(E); } void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits