From: Stanislav Gatev Date: Fri, 28 Jan 2022 16:23:01 +0000 (+0000) Subject: [clang][dataflow] Merge distinct pointer values in Environment::join X-Git-Tag: upstream/15.0.7~18585 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56cc697323445337134cc2bbe8ce8b1f60131574;p=platform%2Fupstream%2Fllvm.git [clang][dataflow] Merge distinct pointer values in Environment::join This is part of the implementation of the dataflow analysis framework. See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev. Reviewed-by: ymandel, xazax.hun Differential Revision: https://reviews.llvm.org/D118480 --- diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 938f733..8392f95 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -89,8 +89,12 @@ LatticeJoinEffect Environment::join(const Environment &Other, if (ExprToLocSizeBefore != ExprToLoc.size()) Effect = LatticeJoinEffect::Changed; - llvm::DenseMap MergedLocToVal; - for (auto &Entry : LocToVal) { + // Move `LocToVal` so that `Environment::Merger::merge` can safely assign + // values to storage locations while this code iterates over the current + // assignments. + llvm::DenseMap OldLocToVal = + std::move(LocToVal); + for (auto &Entry : OldLocToVal) { const StorageLocation *Loc = Entry.first; assert(Loc != nullptr); @@ -103,19 +107,25 @@ LatticeJoinEffect Environment::join(const Environment &Other, assert(It->second != nullptr); if (It->second == Val) { - MergedLocToVal.insert({Loc, Val}); + LocToVal.insert({Loc, Val}); continue; } + if (auto *FirstVal = dyn_cast(Val)) { + auto *SecondVal = cast(It->second); + if (&FirstVal->getPointeeLoc() == &SecondVal->getPointeeLoc()) { + LocToVal.insert({Loc, FirstVal}); + continue; + } + } + // FIXME: Consider destroying `MergedValue` immediately if `Merger::merge` // returns false to avoid storing unneeded values in `DACtx`. if (Value *MergedVal = createValue(Loc->getType())) if (Merger.merge(Loc->getType(), *Val, *It->second, *MergedVal, *this)) - MergedLocToVal.insert({Loc, MergedVal}); + LocToVal.insert({Loc, MergedVal}); } - const unsigned LocToValSizeBefore = LocToVal.size(); - LocToVal = std::move(MergedLocToVal); - if (LocToValSizeBefore != LocToVal.size()) + if (OldLocToVal.size() != LocToVal.size()) Effect = LatticeJoinEffect::Changed; return Effect; diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index ee0bc3e..e9d5e12 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -494,4 +494,37 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) { }); } +TEST_F(WideningTest, DistinctPointersToTheSameLocation) { + std::string Code = R"( + void target(int Foo, bool Cond) { + int *Bar = &Foo; + while (Cond) { + Bar = &Foo; + } + (void)0; + // [[p]] + } + )"; + runDataflow(Code, + [](llvm::ArrayRef< + std::pair>> + 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 auto *FooLoc = cast( + Env.getStorageLocation(*FooDecl, SkipPast::None)); + const auto *BarVal = + cast(Env.getValue(*BarDecl, SkipPast::None)); + EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); + }); +} + } // namespace