diff options
author | martinboehme <mboehme@google.com> | 2023-12-18 09:10:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-18 09:10:03 +0100 |
commit | ca1034341cfec226c09ff0e473c6ecbcc2a1194c (patch) | |
tree | 109ad3d6307f9a701738ef979ecf5e5c7bc919b7 /clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | |
parent | 9bb47f7f8bcc17d90763d201f383d28489b9b071 (diff) | |
download | llvm-ca1034341cfec226c09ff0e473c6ecbcc2a1194c.zip llvm-ca1034341cfec226c09ff0e473c6ecbcc2a1194c.tar.gz llvm-ca1034341cfec226c09ff0e473c6ecbcc2a1194c.tar.bz2 |
[clang][dataflow] Fix an issue with `Environment::getResultObjectLocation()`. (#75483)
So far, if there was a chain of record type prvalues,
`getResultObjectLocation()` would assign a different result object
location to
each one. This makes no sense, of course, as all of these prvalues end
up
initializing the same result object.
This patch fixes this by propagating storage locations up through the
entire
chain of prvalues.
The new implementation also has the desirable effect of making it
possible to
make `getResultObjectLocation()` const, which seems appropriate given
that,
logically, it is just an accessor.
Diffstat (limited to 'clang/unittests/Analysis/FlowSensitive/TransferTest.cpp')
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 8da5595..056c4f3 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2635,6 +2635,55 @@ TEST(TransferTest, BindTemporary) { }); } +TEST(TransferTest, ResultObjectLocation) { + std::string Code = R"( + struct A { + virtual ~A() = default; + }; + + void target() { + A(); + (void)0; // [[p]] + } + )"; + using ast_matchers::cxxBindTemporaryExpr; + using ast_matchers::cxxTemporaryObjectExpr; + using ast_matchers::exprWithCleanups; + using ast_matchers::has; + using ast_matchers::match; + using ast_matchers::selectFirst; + using ast_matchers::traverse; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + // The expresssion `A()` in the code above produces the following + // structure, consisting of three prvalues of record type. + // `Env.getResultObjectLocation()` should return the same location for + // all of these. + auto MatchResult = match( + traverse(TK_AsIs, + exprWithCleanups( + has(cxxBindTemporaryExpr( + has(cxxTemporaryObjectExpr().bind("toe"))) + .bind("bte"))) + .bind("ewc")), + ASTCtx); + auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult); + ASSERT_NE(TOE, nullptr); + auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult); + ASSERT_NE(EWC, nullptr); + auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult); + ASSERT_NE(BTE, nullptr); + + RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE); + EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC)); + EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE)); + }); +} + TEST(TransferTest, StaticCast) { std::string Code = R"( void target(int Foo) { |