[clang] [clang][dataflow] Use `ignoreCFGOmittedNodes()` in `setValue()`. (PR #78245)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 16 01:41:49 PST 2024
https://github.com/martinboehme created https://github.com/llvm/llvm-project/pull/78245
This is to be consistent with `getValue()`, which also uses
`ignoreCFGOmittedNodes()`.
Before this fix, it was not possible to retrieve a `Value` from a "CFG omitted"
node that had previously been set using `setValue()`; see the accompanying test,
which fails without the fix.
I discovered this issue while running internal integration tests on
https://github.com/llvm/llvm-project/pull/78127.
>From 7a3afa03e030563d9377a163778d4eb6b6b3e253 Mon Sep 17 00:00:00 2001
From: Martin Braenne <mboehme at google.com>
Date: Tue, 16 Jan 2024 09:40:51 +0000
Subject: [PATCH] [clang][dataflow] Use `ignoreCFGOmittedNodes()` in
`setValue()`.
This is to be consistent with `getValue()`, which also uses
`ignoreCFGOmittedNodes()`.
Before this fix, it was not possible to retrieve a `Value` from a "CFG omitted"
node that had previously been set using `setValue()`; see the accompanying test,
which fails without the fix.
I discovered this issue while running internal integration tests on
https://github.com/llvm/llvm-project/pull/78127.
---
.../FlowSensitive/DataflowEnvironment.cpp | 10 ++--
.../FlowSensitive/DataflowEnvironmentTest.cpp | 46 +++++++++++++++++++
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 96fe6df88dbb9f..05f8101b0068a3 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -803,13 +803,15 @@ void Environment::setValue(const StorageLocation &Loc, Value &Val) {
}
void Environment::setValue(const Expr &E, Value &Val) {
+ const Expr &CanonE = ignoreCFGOmittedNodes(E);
+
if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
- assert(isOriginalRecordConstructor(E) ||
- &RecordVal->getLoc() == &getResultObjectLocation(E));
+ assert(isOriginalRecordConstructor(CanonE) ||
+ &RecordVal->getLoc() == &getResultObjectLocation(CanonE));
}
- assert(E.isPRValue());
- ExprToVal[&E] = &Val;
+ assert(CanonE.isPRValue());
+ ExprToVal[&CanonE] = &Val;
}
Value *Environment::getValue(const StorageLocation &Loc) const {
diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
index 003434a58b1075..8799d03dfd3c58 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -58,6 +58,52 @@ TEST_F(EnvironmentTest, FlowCondition) {
EXPECT_FALSE(Env.allows(NotX));
}
+TEST_F(EnvironmentTest, SetAndGetValueOnCfgOmittedNodes) {
+ // Check that we can set a value on an expression that is omitted from the CFG
+ // (see `ignoreCFGOmittedNodes()`), then retrieve that same value from the
+ // expression. This is a regression test; `setValue()` and `getValue()`
+ // previously did not use `ignoreCFGOmittedNodes()` consistently.
+
+ using namespace ast_matchers;
+
+ std::string Code = R"cc(
+ struct S {
+ int f();
+ };
+ void target() {
+ // Method call on a temporary produces an `ExprWithCleanups`.
+ S().f();
+ (1);
+ }
+ )cc";
+
+ auto Unit =
+ tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});
+ auto &Context = Unit->getASTContext();
+
+ ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);
+
+ const ExprWithCleanups *WithCleanups = selectFirst<ExprWithCleanups>(
+ "cleanups",
+ match(exprWithCleanups(hasType(isInteger())).bind("cleanups"), Context));
+ ASSERT_NE(WithCleanups, nullptr);
+
+ const ParenExpr *Paren = selectFirst<ParenExpr>(
+ "paren", match(parenExpr(hasType(isInteger())).bind("paren"), Context));
+ ASSERT_NE(Paren, nullptr);
+
+ Environment Env(DAContext);
+ IntegerValue *Val1 =
+ cast<IntegerValue>(Env.createValue(Unit->getASTContext().IntTy));
+ Env.setValue(*WithCleanups, *Val1);
+ EXPECT_EQ(Env.getValue(*WithCleanups), Val1);
+
+ IntegerValue *Val2 =
+ cast<IntegerValue>(Env.createValue(Unit->getASTContext().IntTy));
+ Env.setValue(*Paren, *Val2);
+ EXPECT_EQ(Env.getValue(*Paren), Val2);
+}
+
TEST_F(EnvironmentTest, CreateValueRecursiveType) {
using namespace ast_matchers;
More information about the cfe-commits
mailing list