[clang] [clang][dataflow] Add basic modeling for compound assignments. (PR #179058)
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 31 09:57:10 PST 2026
https://github.com/haoNoQ updated https://github.com/llvm/llvm-project/pull/179058
>From 46f168e87055e737363014c29aaf115fcc1639b9 Mon Sep 17 00:00:00 2001
From: Artem Dergachev <artem.dergachev at gmail.com>
Date: Fri, 30 Jan 2026 16:27:03 -0500
Subject: [PATCH 1/2] [clang][dataflow] Add basic modeling for compound
assignments.
Simularly to #178943, we need to make sure the old value does not stick around.
And for correctness purposes it's better to conjure a fresh value than to
leave it completely unknown.
---
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 25 +++++++++----------
.../Analysis/FlowSensitive/TransferTest.cpp | 6 ++---
2 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 51cc1f9bc26ab..a22e6284df5bc 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -155,21 +155,18 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
const Expr *RHS = S->getRHS();
assert(RHS != nullptr);
- // Do compound assignments up-front, as there are so many of them and we
- // don't want to list all of them in the switch statement below.
- // To avoid generating unnecessary values, we don't create a new value but
- // instead leave it to the specific analysis to do this if desired.
- if (S->isCompoundAssignmentOp())
- propagateStorageLocation(*S->getLHS(), *S, Env);
-
- switch (S->getOpcode()) {
- case BO_Assign: {
+ // Do assignments and compound assignments up-front, as there are
+ // so many of them and we don't want to list all of them in
+ // the switch statement below.
+ if (S->isAssignmentOp()) {
auto *LHSLoc = Env.getStorageLocation(*LHS);
if (LHSLoc == nullptr)
- break;
+ return;
- auto *RHSVal = Env.getValue(*RHS);
- if (RHSVal == nullptr)
+ // Compound assignments involve arithmetic we don't model yet.
+ Value *RHSVal =
+ S->isCompoundAssignmentOp() ? nullptr : Env.getValue(*RHS);
+ if (!RHSVal)
RHSVal = Env.createValue(LHS->getType());
// Assign a value to the storage location of the left-hand side.
@@ -177,8 +174,10 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
// Assign a storage location for the whole expression.
Env.setStorageLocation(*S, *LHSLoc);
- break;
+ return;
}
+
+ switch (S->getOpcode()) {
case BO_LAnd:
case BO_LOr: {
BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index e528ca2221ad1..c0bcb220c3d76 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -990,8 +990,7 @@ TEST(TransferTest, BinaryOperatorAssignUnknown) {
ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooAtCVal));
EXPECT_NE(FooAtAVal, FooAtBVal);
- // FIXME: Should be NE too.
- EXPECT_EQ(FooAtBVal, FooAtCVal);
+ EXPECT_NE(FooAtBVal, FooAtCVal);
// Check that the storage location is correctly propagated.
auto MatchResult = match(binaryOperator().bind("bo"), ASTCtx);
@@ -1006,8 +1005,7 @@ TEST(TransferTest, BinaryOperatorAssignUnknown) {
const Environment &EnvR = getEnvironmentAtAnnotation(Results, "r");
EXPECT_FALSE(EnvQ.proves(EnvQ.arena().makeLiteral(false)));
- // FIXME: Should be FALSE too.
- EXPECT_TRUE(EnvR.proves(EnvR.arena().makeLiteral(false)));
+ EXPECT_FALSE(EnvR.proves(EnvR.arena().makeLiteral(false)));
});
}
>From c6754b31a7356271cb3677b26d3bdd4b8a4b9f1a Mon Sep 17 00:00:00 2001
From: Artem Dergachev <artem.dergachev at gmail.com>
Date: Sat, 31 Jan 2026 12:56:24 -0500
Subject: [PATCH 2/2] [clang][dataflow] Fixup: Preserve style.
---
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index a22e6284df5bc..b2ea9a1ce02e8 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -166,7 +166,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
// Compound assignments involve arithmetic we don't model yet.
Value *RHSVal =
S->isCompoundAssignmentOp() ? nullptr : Env.getValue(*RHS);
- if (!RHSVal)
+ if (RHSVal == nullptr)
RHSVal = Env.createValue(LHS->getType());
// Assign a value to the storage location of the left-hand side.
More information about the cfe-commits
mailing list