This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGbaa0f221d6df: [clang][dataflow] Update StructValue child when assigning a value (authored by sgatev).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D120414/new/ https://reviews.llvm.org/D120414 Files: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2320,4 +2320,48 @@ }); } +TEST_F(TransferTest, AssignMemberBeforeCopy) { + std::string Code = R"( + struct A { + int Foo; + }; + + void target() { + A A1; + A A2; + int Bar; + A1.Foo = Bar; + A2 = A1; + // [[p]] + } + )"; + runDataflow(Code, + [](llvm::ArrayRef< + std::pair<std::string, DataflowAnalysisState<NoopLattice>>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; + + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); + + const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); + ASSERT_THAT(BarDecl, NotNull()); + + const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); + ASSERT_THAT(A1Decl, NotNull()); + + const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); + ASSERT_THAT(A2Decl, NotNull()); + + const auto *BarVal = + cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); + + const auto *A2Val = + cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); + EXPECT_EQ(&A2Val->getChild(*FooDecl), BarVal); + }); +} + } // namespace Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -138,6 +138,9 @@ if (ExprToLoc != Other.ExprToLoc) return false; + if (MemberLocToStruct != Other.MemberLocToStruct) + return false; + if (LocToVal.size() != Other.LocToVal.size()) return false; @@ -176,6 +179,12 @@ if (ExprToLocSizeBefore != ExprToLoc.size()) Effect = LatticeJoinEffect::Changed; + const unsigned MemberLocToStructSizeBefore = MemberLocToStruct.size(); + MemberLocToStruct = + intersectDenseMaps(MemberLocToStruct, Other.MemberLocToStruct); + if (MemberLocToStructSizeBefore != MemberLocToStruct.size()) + Effect = LatticeJoinEffect::Changed; + // Move `LocToVal` so that `Environment::ValueModel::merge` can safely assign // values to storage locations while this code iterates over the current // assignments. @@ -285,9 +294,25 @@ for (const FieldDecl *Field : Type->getAsRecordDecl()->fields()) { assert(Field != nullptr); - setValue(AggregateLoc.getChild(*Field), StructVal->getChild(*Field)); + StorageLocation &FieldLoc = AggregateLoc.getChild(*Field); + MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field); + setValue(FieldLoc, StructVal->getChild(*Field)); } } + + auto IT = MemberLocToStruct.find(&Loc); + if (IT != MemberLocToStruct.end()) { + // `Loc` is the location of a struct member so we need to also update the + // value of the member in the corresponding `StructValue`. + + assert(IT->second.first != nullptr); + StructValue &StructVal = *IT->second.first; + + assert(IT->second.second != nullptr); + const ValueDecl &Member = *IT->second.second; + + StructVal.setChild(Member, Val); + } } Value *Environment::getValue(const StorageLocation &Loc) const { Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h =================================================================== --- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -265,6 +265,12 @@ llvm::DenseMap<const StorageLocation *, Value *> LocToVal; + // Maps locations of struct members to symbolic values of the structs that own + // them and the decls of the struct members. + llvm::DenseMap<const StorageLocation *, + std::pair<StructValue *, const ValueDecl *>> + MemberLocToStruct; + // FIXME: Add flow condition constraints. };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits