aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
diff options
context:
space:
mode:
authormartinboehme <mboehme@google.com>2023-12-18 09:10:03 +0100
committerGitHub <noreply@github.com>2023-12-18 09:10:03 +0100
commitca1034341cfec226c09ff0e473c6ecbcc2a1194c (patch)
tree109ad3d6307f9a701738ef979ecf5e5c7bc919b7 /clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
parent9bb47f7f8bcc17d90763d201f383d28489b9b071 (diff)
downloadllvm-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.cpp49
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) {