-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][dataflow] Use ignoreCFGOmittedNodes()
in setValue()
.
#78245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][dataflow] Use ignoreCFGOmittedNodes()
in setValue()
.
#78245
Conversation
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 llvm#78127.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-analysis Author: None (martinboehme) ChangesThis is to be consistent with Before this fix, it was not possible to retrieve a I discovered this issue while running internal integration tests on Full diff: https://github.com/llvm/llvm-project/pull/78245.diff 2 Files Affected:
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 96fe6df88dbb9f7..05f8101b0068a31 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 003434a58b1075f..8799d03dfd3c588 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;
|
…m#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 llvm#78127.
This is to be consistent with
getValue()
, which also usesignoreCFGOmittedNodes()
.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
#78127.