[clang] [NFC][analyzer] Improve code quality in VisitBinaryOperator (PR #205151)
DonĂ¡t Nagy via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 30 04:16:40 PDT 2026
https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/205151
>From f4916c3f3bb60e776e30dbea2f0b81af064f6b51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 16:57:43 +0200
Subject: [PATCH 01/12] Modernize an old-style loop
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index f2682b25630e1..7e2ff8146dbe3 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -51,11 +51,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this);
// With both the LHS and RHS evaluated, process the operation itself.
- for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end();
- it != ei; ++it) {
-
- ProgramStateRef state = (*it)->getState();
- const StackFrame *SF = (*it)->getStackFrame();
+ for (ExplodedNode *N : CheckedSet) {
+ ProgramStateRef state = N->getState();
+ const StackFrame *SF = N->getStackFrame();
SVal LeftV = state->getSVal(LHS, SF);
SVal RightV = state->getSVal(RHS, SF);
@@ -72,13 +70,13 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
SVal ExprVal = B->isGLValue() ? LeftV : RightV;
- evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, SF, ExprVal), LeftV,
+ evalStore(Tmp2, B, LHS, N, state->BindExpr(B, SF, ExprVal), LeftV,
RightV);
continue;
}
if (!B->isAssignmentOp()) {
- NodeBuilder Bldr(*it, Tmp2, *currBldrCtx);
+ NodeBuilder Bldr(N, Tmp2, *currBldrCtx);
if (B->isAdditiveOp()) {
// TODO: This can be removed after we enable history tracking with
@@ -109,7 +107,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
state = escapeValues(state, RightV, PSK_EscapeOther);
}
- Bldr.generateNode(B, *it, state);
+ Bldr.generateNode(B, N, state);
continue;
}
@@ -134,7 +132,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// null dereferences, and so on.
ExplodedNodeSet Tmp;
SVal location = LeftV;
- evalLoad(Tmp, B, LHS, *it, state, location);
+ evalLoad(Tmp, B, LHS, N, state, location);
for (ExplodedNode *N : Tmp) {
state = N->getState();
>From 21862d54e5cd0c611370e8ef43f1d45940d47ea1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 17:47:34 +0200
Subject: [PATCH 02/12] Conjured symbols are 15 year old, no longer
EXPERIMENTAL
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 7e2ff8146dbe3..3dfeb1ad15002 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -60,7 +60,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
BinaryOperator::Opcode Op = B->getOpcode();
if (Op == BO_Assign) {
- // EXPERIMENTAL: "Conjured" symbols.
// FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = getNumVisitedCurrent();
@@ -157,7 +156,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
B->getType(), CTy);
- // EXPERIMENTAL: "Conjured" symbols.
// FIXME: Handle structs.
SVal LHSVal;
>From 0cc42c42c1222bd57f846bbe9ee523a142e49452 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 17:54:09 +0200
Subject: [PATCH 03/12] Remove obsolete FIXMEs from 2011
Assignment operartors do "Handle structs" nowdays, and builtin compound
assignment operators (like `+=`) don't need to handle structs.
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 3dfeb1ad15002..312c1941d1616 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -60,7 +60,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
BinaryOperator::Opcode Op = B->getOpcode();
if (Op == BO_Assign) {
- // FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = getNumVisitedCurrent();
RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
@@ -156,8 +155,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
B->getType(), CTy);
- // FIXME: Handle structs.
-
SVal LHSVal;
if (Result.isUnknown()) {
>From 680dee983e13ebc3ac750835b10e5e11a435ebd0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 18:04:20 +0200
Subject: [PATCH 04/12] Remove obsolete TODO from 2012
This code block handles `pointer + integer`, `pointer - integer` or
`integer + pointer` expressions, which produce values that are
represeted by element regions (wrapped in `loc::MemRegionVal`).
Perhaps some old plans hoped to use `SymSymExpr` (or perhaps
`SymIntExpr`) in these situations, but they are irrelevant now.
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 312c1941d1616..dc2bc9e681bcd 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -77,8 +77,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
NodeBuilder Bldr(N, Tmp2, *currBldrCtx);
if (B->isAdditiveOp()) {
- // TODO: This can be removed after we enable history tracking with
- // SymSymExpr.
unsigned Count = getNumVisitedCurrent();
RightV = conjureOffsetSymbolOnLocation(
RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
>From b7606aefc3fb4a16084ef17693592b49bfab3da6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 18:29:38 +0200
Subject: [PATCH 05/12] Capitalize local 'state'
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index dc2bc9e681bcd..4e14062d27c39 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -52,10 +52,10 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// With both the LHS and RHS evaluated, process the operation itself.
for (ExplodedNode *N : CheckedSet) {
- ProgramStateRef state = N->getState();
+ ProgramStateRef State = N->getState();
const StackFrame *SF = N->getStackFrame();
- SVal LeftV = state->getSVal(LHS, SF);
- SVal RightV = state->getSVal(RHS, SF);
+ SVal LeftV = State->getSVal(LHS, SF);
+ SVal RightV = State->getSVal(RHS, SF);
BinaryOperator::Opcode Op = B->getOpcode();
@@ -68,7 +68,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
SVal ExprVal = B->isGLValue() ? LeftV : RightV;
- evalStore(Tmp2, B, LHS, N, state->BindExpr(B, SF, ExprVal), LeftV,
+ evalStore(Tmp2, B, LHS, N, State->BindExpr(B, SF, ExprVal), LeftV,
RightV);
continue;
}
@@ -90,20 +90,20 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// sure that the members of temporaries have a valid 'this' pointer for
// other checks.
if (B->getOpcode() == BO_PtrMemD)
- state = createTemporaryRegionIfNeeded(state, SF, LHS);
+ State = createTemporaryRegionIfNeeded(State, SF, LHS);
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
- SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
+ SVal Result = evalBinOp(State, Op, LeftV, RightV, B->getType());
if (!Result.isUnknown()) {
- state = state->BindExpr(B, SF, Result);
+ State = State->BindExpr(B, SF, Result);
} else {
// If we cannot evaluate the operation escape the operands.
- state = escapeValues(state, LeftV, PSK_EscapeOther);
- state = escapeValues(state, RightV, PSK_EscapeOther);
+ State = escapeValues(State, LeftV, PSK_EscapeOther);
+ State = escapeValues(State, RightV, PSK_EscapeOther);
}
- Bldr.generateNode(B, N, state);
+ Bldr.generateNode(B, N, State);
continue;
}
@@ -128,12 +128,12 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// null dereferences, and so on.
ExplodedNodeSet Tmp;
SVal location = LeftV;
- evalLoad(Tmp, B, LHS, N, state, location);
+ evalLoad(Tmp, B, LHS, N, State, location);
for (ExplodedNode *N : Tmp) {
- state = N->getState();
+ State = N->getState();
const StackFrame *SF = N->getStackFrame();
- SVal V = state->getSVal(LHS, SF);
+ SVal V = State->getSVal(LHS, SF);
// Get the computation type.
QualType CTy =
@@ -150,7 +150,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
V = svalBuilder.evalCast(V, CLHSTy, LTy);
// Compute the result of the operation.
- SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
+ SVal Result = svalBuilder.evalCast(evalBinOp(State, Op, V, RightV, CTy),
B->getType(), CTy);
SVal LHSVal;
@@ -173,11 +173,11 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// In C++, assignment and compound assignment operators return an
// lvalue.
if (B->isGLValue())
- state = state->BindExpr(B, SF, location);
+ State = State->BindExpr(B, SF, location);
else
- state = state->BindExpr(B, SF, Result);
+ State = State->BindExpr(B, SF, Result);
- evalStore(Tmp2, B, LHS, N, state, location, LHSVal);
+ evalStore(Tmp2, B, LHS, N, State, location, LHSVal);
}
}
>From e16ed8e7c6bef1e47620091327001abb6f993f62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 18:32:58 +0200
Subject: [PATCH 06/12] Eliminate redundant variable 'location'
At this point the code switches to using 'location' as the new name of
'LeftV' which is confusing.
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 4e14062d27c39..0e32c18b32ffa 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -127,8 +127,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
ExplodedNodeSet Tmp;
- SVal location = LeftV;
- evalLoad(Tmp, B, LHS, N, State, location);
+ evalLoad(Tmp, B, LHS, N, State, LeftV);
for (ExplodedNode *N : Tmp) {
State = N->getState();
@@ -153,7 +152,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
SVal Result = svalBuilder.evalCast(evalBinOp(State, Op, V, RightV, CTy),
B->getType(), CTy);
- SVal LHSVal;
+ SVal LHSVal; // Value that will be stored at location specifed by LeftV.
if (Result.isUnknown()) {
// The symbolic value is actually for the type of the left-hand side
@@ -173,11 +172,11 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// In C++, assignment and compound assignment operators return an
// lvalue.
if (B->isGLValue())
- State = State->BindExpr(B, SF, location);
+ State = State->BindExpr(B, SF, LeftV);
else
State = State->BindExpr(B, SF, Result);
- evalStore(Tmp2, B, LHS, N, State, location, LHSVal);
+ evalStore(Tmp2, B, LHS, N, State, LeftV, LHSVal);
}
}
>From 0e812af949b24c45f4e66ba8f2672554d6c60175 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 18:45:02 +0200
Subject: [PATCH 07/12] Use a self-documenting variable name
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 0e32c18b32ffa..63e2793dd1a8b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -152,21 +152,21 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
SVal Result = svalBuilder.evalCast(evalBinOp(State, Op, V, RightV, CTy),
B->getType(), CTy);
- SVal LHSVal; // Value that will be stored at location specifed by LeftV.
+ SVal StoredInLeftV;
if (Result.isUnknown()) {
// The symbolic value is actually for the type of the left-hand side
// expression, not the computation type, as this is the value the
// LValue on the LHS will bind to.
- LHSVal = svalBuilder.conjureSymbolVal(/*symbolTag=*/nullptr,
- getCFGElementRef(), SF, LTy,
- getNumVisitedCurrent());
+ StoredInLeftV = svalBuilder.conjureSymbolVal(
+ /*symbolTag=*/nullptr, getCFGElementRef(), SF, LTy,
+ getNumVisitedCurrent());
// However, we need to convert the symbol to the computation type.
- Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
+ Result = svalBuilder.evalCast(StoredInLeftV, CTy, LTy);
} else {
// The left-hand side may bind to a different value then the
// computation type.
- LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
+ StoredInLeftV = svalBuilder.evalCast(Result, LTy, CTy);
}
// In C++, assignment and compound assignment operators return an
@@ -176,7 +176,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
else
State = State->BindExpr(B, SF, Result);
- evalStore(Tmp2, B, LHS, N, State, LeftV, LHSVal);
+ evalStore(Tmp2, B, LHS, N, State, LeftV, StoredInLeftV);
}
}
>From ab9bda29f664335d5dd1624fb841e4d930514705 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 18:45:29 +0200
Subject: [PATCH 08/12] Simplify getting the relevant types
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 63e2793dd1a8b..2d6594d7d2dce 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -134,15 +134,11 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
const StackFrame *SF = N->getStackFrame();
SVal V = State->getSVal(LHS, SF);
- // Get the computation type.
- QualType CTy =
- cast<CompoundAssignOperator>(B)->getComputationResultType();
- CTy = getContext().getCanonicalType(CTy);
-
- QualType CLHSTy =
- cast<CompoundAssignOperator>(B)->getComputationLHSType();
- CLHSTy = getContext().getCanonicalType(CLHSTy);
-
+ // Determine the relevant types.
+ const ASTContext &ACtx = getContext();
+ const auto *CAOpB = cast<CompoundAssignOperator>(B);
+ QualType CTy = ACtx.getCanonicalType(CAOpB->getComputationResultType());
+ QualType CLHSTy = ACtx.getCanonicalType(CAOpB->getComputationLHSType());
QualType LTy = getContext().getCanonicalType(LHS->getType());
// Promote LHS.
>From 99820f279d74d6e6e2cda382311f6963d73931c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 19:01:51 +0200
Subject: [PATCH 09/12] Replace verbose helper function with lambda
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 37 ++++++-------------
1 file changed, 12 insertions(+), 25 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2d6594d7d2dce..26b798fbfd87a 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -20,24 +20,6 @@ using namespace clang;
using namespace ento;
using llvm::APSInt;
-/// Optionally conjure and return a symbol for offset when processing
-/// \p Elem.
-/// If \p Other is a location, conjure a symbol for \p Symbol
-/// (offset) if it is unknown so that memory arithmetic always
-/// results in an ElementRegion.
-/// \p Count The number of times the current basic block was visited.
-static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
- ConstCFGElementRef Elem, QualType Ty,
- SValBuilder &svalBuilder,
- unsigned Count,
- const StackFrame *SF) {
- if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
- Symbol.isUnknown()) {
- return svalBuilder.conjureSymbolVal(Elem, SF, Ty, Count);
- }
- return Symbol;
-}
-
void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -77,13 +59,18 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
NodeBuilder Bldr(N, Tmp2, *currBldrCtx);
if (B->isAdditiveOp()) {
- unsigned Count = getNumVisitedCurrent();
- RightV = conjureOffsetSymbolOnLocation(
- RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
- Count, SF);
- LeftV = conjureOffsetSymbolOnLocation(LeftV, RightV, getCFGElementRef(),
- LHS->getType(), svalBuilder,
- Count, SF);
+ // Ensure that if `p` is a pointer and `i` is an integer with Unknown
+ // value, then `p+i`, `i+p` and `p-i` are evaluated to element regions
+ // (with a symbolic offset) instead of Unknown.
+ auto ConjureIfNeeded = [this, SF](SVal &V, SVal Other, QualType VTy) {
+ if (isa<Loc>(Other) && VTy->isIntegralOrEnumerationType() &&
+ V.isUnknown()) {
+ V = svalBuilder.conjureSymbolVal(getCFGElementRef(), SF, VTy,
+ getNumVisitedCurrent());
+ }
+ };
+ ConjureIfNeeded(RightV, LeftV, RHS->getType());
+ ConjureIfNeeded(LeftV, RightV, LHS->getType());
}
// Although we don't yet model pointers-to-members, we do need to make
>From 98db32fc849bf8ee25530596c14790ba15540586 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 19:09:57 +0200
Subject: [PATCH 10/12] Remove the NodeBuilder from VisitBinaryOperator
This was a very trivial `NodeBuilder` that unconditionally generated
exactly one node. (Its constructor was inserting `N` into `Tmp2` but
this was irrelevant because the `generateNode` cancelled it out.)
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 26b798fbfd87a..c8e5343b1fc16 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -56,8 +56,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
}
if (!B->isAssignmentOp()) {
- NodeBuilder Bldr(N, Tmp2, *currBldrCtx);
-
if (B->isAdditiveOp()) {
// Ensure that if `p` is a pointer and `i` is an integer with Unknown
// value, then `p+i`, `i+p` and `p-i` are evaluated to element regions
@@ -90,7 +88,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
State = escapeValues(State, RightV, PSK_EscapeOther);
}
- Bldr.generateNode(B, N, State);
+ Tmp2.insert(Engine.makePostStmtNode(B, State, N));
continue;
}
>From 3ed15379174b6520b459ed1c45e59f91c682d62d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Mon, 22 Jun 2026 19:13:33 +0200
Subject: [PATCH 11/12] Declare StackFrame *SF at top of method
The relevant StackFrame only changes when the analysis enters or leaves
an inlined function call, so we can query the same `SF` from any
reasonably recent exploded node.
As this boilerplate definition does not carry useful information, I
prefer to place it at the very beginning of the method.
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index c8e5343b1fc16..96238b0ddcd05 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -23,6 +23,7 @@ using llvm::APSInt;
void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
+ const StackFrame *SF = Pred->getStackFrame();
Expr *LHS = B->getLHS()->IgnoreParens();
Expr *RHS = B->getRHS()->IgnoreParens();
@@ -35,7 +36,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// With both the LHS and RHS evaluated, process the operation itself.
for (ExplodedNode *N : CheckedSet) {
ProgramStateRef State = N->getState();
- const StackFrame *SF = N->getStackFrame();
SVal LeftV = State->getSVal(LHS, SF);
SVal RightV = State->getSVal(RHS, SF);
@@ -116,7 +116,6 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
for (ExplodedNode *N : Tmp) {
State = N->getState();
- const StackFrame *SF = N->getStackFrame();
SVal V = State->getSVal(LHS, SF);
// Determine the relevant types.
>From 3c5b0e9a4540a402cb4cd2d2d9b3124045e1fc42 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Tue, 30 Jun 2026 13:16:16 +0200
Subject: [PATCH 12/12] Use `ACtx` to refer to the ASTContext
---
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 96238b0ddcd05..33c31fe10782a 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -123,7 +123,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
const auto *CAOpB = cast<CompoundAssignOperator>(B);
QualType CTy = ACtx.getCanonicalType(CAOpB->getComputationResultType());
QualType CLHSTy = ACtx.getCanonicalType(CAOpB->getComputationLHSType());
- QualType LTy = getContext().getCanonicalType(LHS->getType());
+ QualType LTy = ACtx.getCanonicalType(LHS->getType());
// Promote LHS.
V = svalBuilder.evalCast(V, CLHSTy, LTy);
More information about the cfe-commits
mailing list