[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
wyt created this revision. Herald added subscribers: martong, tschuett, xazax.hun. Herald added a project: All. wyt requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. `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`. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D128359 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ } } -// 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 &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 getObjectFields(QualType Type) { - llvm::DenseSet Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,15 @@ } 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 FieldLocs; -for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); -return takeOwnership( -std::make_unique(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique(Type)); + return DACtx->createStorageLocation(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->createStorageLocation(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->createStorageLocation(E); } void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -22,6 +22,43 @@ namespace clang { namespace dataflow { +StorageLocation &DataflowAnalysisContext::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 FieldLocs; +for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); +return takeOwnership( +std::make_unique(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique(Type)); +} + +StorageLocation & +DataflowAnalysisContext::createStorageLocation(const VarDecl &D) { + // Evaluated declarations are always assigned the same storage locations to + // ensur
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
sgatev added inline comments. Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:91-92 + // FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`, + // `getStableStorageLocation`, or something more appropriate. + Let's implement this for the new members you are adding and keep the existing members in `DataflowEnvironment` as they are. I suggest calling the new ones `getStableStorageLocation`. Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:94-95 + + /// Creates a storage location appropriate for `Type`. Does not assign a value + /// to the returned storage location in the environment. + /// Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:102-104 + /// Creates a storage location for `D`. Does not assign the returned storage + /// location to `D` in the environment. Does not assign a value to the + /// returned storage location in the environment. Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:107-109 + /// Creates a storage location for `E`. Does not assign the returned storage + /// location to `E` in the environment. Does not assign a value to the + /// returned storage location in the environment. Comment at: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp:41-43 + // 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. I think it makes sense to keep this comment in the wrapper in `DataflowEnvironment`. Same for the one below. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
wyt updated this revision to Diff 439720. wyt marked 5 inline comments as done. wyt added a comment. Address comments. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ } } -// 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 &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 getObjectFields(QualType Type) { - llvm::DenseSet Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,21 @@ } 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 FieldLocs; -for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); -return takeOwnership( -std::make_unique(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique(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) { Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ 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 FieldLocs; +for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())}); +return takeOwnership( +std::make_unique(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique(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); + re
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
sgatev accepted this revision. sgatev added inline comments. This revision is now accepted and ready to land. Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:91 + /// Creates a stable storage location appropriate for `Type`. + /// Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:98 + + /// Creates a stable storage location for `D`. + StorageLocation &getStableStorageLocation(const VarDecl &D); Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:101 + + /// Creates a stable storage location for `E`. + StorageLocation &getStableStorageLocation(const Expr &E); Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
wyt updated this revision to Diff 439730. wyt marked 3 inline comments as done. wyt added a comment. Fix comment. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ } } -// 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 &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 getObjectFields(QualType Type) { - llvm::DenseSet Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,21 @@ } 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 FieldLocs; -for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); -return takeOwnership( -std::make_unique(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique(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) { Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ 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 FieldLocs; +for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())}); +return takeOwnership( +std::make_unique(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique(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
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
gribozavr2 accepted this revision. gribozavr2 added inline comments. Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h:47 +/// Gets the set of all fields in the type. +llvm::DenseSet getObjectFields(QualType Type); Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
wyt updated this revision to Diff 440123. wyt marked an inline comment as done. wyt added a comment. Fix comment. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ } } -// 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 &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 getObjectFields(QualType Type) { - llvm::DenseSet Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,21 @@ } 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 FieldLocs; -for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); -return takeOwnership( -std::make_unique(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique(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) { Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ 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 FieldLocs; +for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())}); +return takeOwnership( +std::make_unique(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique(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
[PATCH] D128359: [clang][dataflow] Move logic for `createStorageLocation` from `DataflowEnvironment` to `DataflowAnalysisContext`.
This revision was automatically updated to reflect the committed changes. Closed by commit rG12c7352fa488: [clang][dataflow] Move logic for `createStorageLocation` from… (authored by wyt, committed by gribozavr). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D128359/new/ https://reviews.llvm.org/D128359 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -152,29 +152,6 @@ } } -// 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 &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 getObjectFields(QualType Type) { - llvm::DenseSet Fields; - getFieldsFromClassHierarchy(Type, Fields); - return Fields; -} - Environment::Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} @@ -310,39 +287,21 @@ } 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 FieldLocs; -for (const FieldDecl *Field : getObjectFields(Type)) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); -return takeOwnership( -std::make_unique(Type, std::move(FieldLocs))); - } - return takeOwnership(std::make_unique(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) { Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp === --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ 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 FieldLocs; +for (const FieldDecl *Field : getObjectFields(Type)) + FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())}); +return takeOwnership( +std::make_unique(Type, std::move(FieldLocs))); + } + return takeOwnership(std::make_unique(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 *Lo