https://github.com/NagyDonat created 
https://github.com/llvm/llvm-project/pull/186186

Previously the method `ExprEngine::computeObjectUnderConstruction` took a 
`NodeBuilderContext` parameter which was only used to call its `blockCount()` 
method; this commit replaces this with directly taking `NumVisitedCaller` (= 
number of times the caller was visited, the `blockCount`) as an `unsigned` 
value.

Also leave a FIXME comment on some logic that seems to be fishy (I _suspect_ 
that sometimes it uses the wrong `LocationContext` and `Block`, but I'm not 
certain.)

From 22f9ce383d8468bf28c8e29579123db534c6e00a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]>
Date: Tue, 10 Mar 2026 11:39:16 +0100
Subject: [PATCH 1/2] [NFC][analyzer] Simplify computeObjectUnderConstruction
 part 1

Previously the method `ExprEngine::computeObjectUnderConstruction` took
a `NodeBuilderContext` parameter which was only used to call its
`blockCount()` method; this commit replaces this with directly taking
`NumVisitedCaller` (= number of times the caller was visited, the
`blockCount`) as an `unsigned` value.

This moves toward the elimination of the type `NodeBuilderContext`.
Note that I'm using the name `NumVisitedCaller` instead of e.g.
`CallerBlockCount` because I think this is more self-documenting.

This commit leaves behind some non-idiomatic constructs which will be
cleaned up in an immediate follow-up.
---
 .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h    |  6 +++---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp           |  2 +-
 clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp       | 11 ++++++-----
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 2023a7a5b1ac8..360a260d4d803 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -796,7 +796,7 @@ class ExprEngine {
   /// A multi-dimensional array is also a continuous memory location in a
   /// row major order, so for arr[0][0] Idx is 0 and for arr[3][3] Idx is 8.
   SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State,
-                                      const NodeBuilderContext *BldrCtx,
+                                      unsigned NumVisitedCaller,
                                       const LocationContext *LCtx,
                                       const ConstructionContext *CC,
                                       EvalCallOptions &CallOpts,
@@ -818,8 +818,8 @@ class ExprEngine {
       const LocationContext *LCtx, const ConstructionContext *CC,
       EvalCallOptions &CallOpts, unsigned Idx = 0) {
 
-    SVal V = computeObjectUnderConstruction(E, State, BldrCtx, LCtx, CC,
-                                            CallOpts, Idx);
+    SVal V = computeObjectUnderConstruction(E, State, BldrCtx->blockCount(),
+                                            LCtx, CC, CallOpts, Idx);
     State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts);
 
     return std::make_pair(State, V);
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index f6c3a8e3266da..cff3116caf6e6 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -563,7 +563,7 @@ std::optional<SVal> 
CallEvent::getReturnValueUnderConstruction() const {
   EvalCallOptions CallOpts;
   ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
   SVal RetVal = Engine.computeObjectUnderConstruction(
-      getOriginExpr(), getState(), &Engine.getBuilderContext(),
+      getOriginExpr(), getState(), Engine.getBuilderContext().blockCount(),
       getLocationContext(), CC, CallOpts);
   return RetVal;
 }
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 0866dda766667..c91b5ddd0d46e 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -129,7 +129,7 @@ SVal ExprEngine::makeElementRegion(ProgramStateRef State, 
SVal LValue,
 // it's materialization happens in context of the caller.
 // We pass BldrCtx explicitly, as currBldrCtx always refers to callee's 
context.
 SVal ExprEngine::computeObjectUnderConstruction(
-    const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx,
+    const Expr *E, ProgramStateRef State, unsigned NumVisitedCaller,
     const LocationContext *LCtx, const ConstructionContext *CC,
     EvalCallOptions &CallOpts, unsigned Idx) {
 
@@ -232,8 +232,9 @@ SVal ExprEngine::computeObjectUnderConstruction(
 
         NodeBuilderContext CallerBldrCtx(getCoreEngine(),
                                          SFC->getCallSiteBlock(), CallerLCtx);
+        unsigned NumVisitedCaller = CallerBldrCtx.blockCount();
         return computeObjectUnderConstruction(
-            cast<Expr>(SFC->getCallSite()), State, &CallerBldrCtx, CallerLCtx,
+            cast<Expr>(SFC->getCallSite()), State, NumVisitedCaller, 
CallerLCtx,
             RTC->getConstructionContext(), CallOpts);
       } else {
         // We are on the top frame of the analysis. We do not know where is the
@@ -273,7 +274,7 @@ SVal ExprEngine::computeObjectUnderConstruction(
       EvalCallOptions PreElideCallOpts = CallOpts;
 
       SVal V = computeObjectUnderConstruction(
-          TCC->getConstructorAfterElision(), State, BldrCtx, LCtx,
+          TCC->getConstructorAfterElision(), State, NumVisitedCaller, LCtx,
           TCC->getConstructionContextAfterElision(), CallOpts);
 
       // FIXME: This definition of "copy elision has not failed" is unreliable.
@@ -346,7 +347,7 @@ SVal ExprEngine::computeObjectUnderConstruction(
       CallEventManager &CEMgr = getStateManager().getCallEventManager();
       auto getArgLoc = [&](CallEventRef<> Caller) -> std::optional<SVal> {
         const LocationContext *FutureSFC =
-            Caller->getCalleeStackFrame(BldrCtx->blockCount());
+            Caller->getCalleeStackFrame(NumVisitedCaller);
         // Return early if we are unable to reliably foresee
         // the future stack frame.
         if (!FutureSFC)
@@ -365,7 +366,7 @@ SVal ExprEngine::computeObjectUnderConstruction(
         // because this-argument is implemented as a normal argument in
         // operator call expressions but not in operator declarations.
         const TypedValueRegion *TVR = Caller->getParameterLocation(
-            *Caller->getAdjustedParameterIndex(Idx), BldrCtx->blockCount());
+            *Caller->getAdjustedParameterIndex(Idx), NumVisitedCaller);
         if (!TVR)
           return std::nullopt;
 

From a80473647ab61fb3d4a1a60c91441652c72df4d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]>
Date: Tue, 10 Mar 2026 14:22:43 +0100
Subject: [PATCH 2/2] [NFC][analyzer] Simplify computeObjectUnderConstruction
 part 2

Clean-up non-idiomatic code left behind by the previous change.

Also leave a FIXME comment on some logic that seems to be fishy (I
_suspect_ that sometimes it uses the wrong LocationContext and Block,
but I'm not certain.)
---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp     | 6 +++++-
 clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 7 ++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index cff3116caf6e6..86ffd92cdf6f5 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -562,8 +562,12 @@ std::optional<SVal> 
CallEvent::getReturnValueUnderConstruction() const {
 
   EvalCallOptions CallOpts;
   ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
+  // FIXME: This code assumes that the _current_ location context and block is
+  // the location and block where this `CallExpr` is called. For a more stable
+  // solution `Engine.getNumVisitedCurrent()` should be replaced with a call to
+  // `Engine.getNumVisited(<CallerLCtx>, <CallerBlock>)`.
   SVal RetVal = Engine.computeObjectUnderConstruction(
-      getOriginExpr(), getState(), Engine.getBuilderContext().blockCount(),
+      getOriginExpr(), getState(), Engine.getNumVisitedCurrent(),
       getLocationContext(), CC, CallOpts);
   return RetVal;
 }
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index c91b5ddd0d46e..cf22b62225f2f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -127,7 +127,6 @@ SVal ExprEngine::makeElementRegion(ProgramStateRef State, 
SVal LValue,
 // In case when the prvalue is returned from the function (kind is one of
 // SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind), then
 // it's materialization happens in context of the caller.
-// We pass BldrCtx explicitly, as currBldrCtx always refers to callee's 
context.
 SVal ExprEngine::computeObjectUnderConstruction(
     const Expr *E, ProgramStateRef State, unsigned NumVisitedCaller,
     const LocationContext *LCtx, const ConstructionContext *CC,
@@ -230,11 +229,9 @@ SVal ExprEngine::computeObjectUnderConstruction(
           assert(!isa<BlockInvocationContext>(CallerLCtx));
         }
 
-        NodeBuilderContext CallerBldrCtx(getCoreEngine(),
-                                         SFC->getCallSiteBlock(), CallerLCtx);
-        unsigned NumVisitedCaller = CallerBldrCtx.blockCount();
+        unsigned NVCaller = getNumVisited(CallerLCtx, SFC->getCallSiteBlock());
         return computeObjectUnderConstruction(
-            cast<Expr>(SFC->getCallSite()), State, NumVisitedCaller, 
CallerLCtx,
+            cast<Expr>(SFC->getCallSite()), State, NVCaller, CallerLCtx,
             RTC->getConstructionContext(), CallOpts);
       } else {
         // We are on the top frame of the analysis. We do not know where is the

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to