[clang] [Clang][analyzer] replace Stmt* with ConstCFGElementRef in SymbolConjured (PR #128251)

Fangyi Zhou via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 22 17:16:19 PST 2025


https://github.com/fangyi-zhou updated https://github.com/llvm/llvm-project/pull/128251

>From 85af3970159e2c6676c9a60f606322d89c57c078 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Fri, 21 Feb 2025 20:54:08 +0000
Subject: [PATCH 01/12] WIP: use CFGElement in conjuredSymbol

---
 .../Core/PathSensitive/SValBuilder.h          | 87 +++++++++--------
 .../Core/PathSensitive/SymbolManager.h        | 56 +++++++----
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  | 18 ++--
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 55 ++++++-----
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 13 +--
 .../Core/ExprEngineCallAndReturn.cpp          |  6 +-
 .../StaticAnalyzer/Core/ExprEngineObjC.cpp    | 16 ++--
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 93 +++++++++++--------
 8 files changed, 200 insertions(+), 144 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 54430d426a82a..5b2887b0f9a86 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -19,6 +19,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/Type.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
@@ -171,20 +172,27 @@ class SValBuilder {
 
   // Forwarding methods to SymbolManager.
 
-  const SymbolConjured* conjureSymbol(const Stmt *stmt,
+  const SymbolConjured *conjureSymbol(const CFGBlock::CFGElementRef ElemRef,
                                       const LocationContext *LCtx,
-                                      QualType type,
-                                      unsigned visitCount,
+                                      QualType type, unsigned visitCount,
                                       const void *symbolTag = nullptr) {
-    return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
+    return SymMgr.conjureSymbol(ElemRef, LCtx, type, visitCount, symbolTag);
   }
 
-  const SymbolConjured* conjureSymbol(const Expr *expr,
-                                      const LocationContext *LCtx,
-                                      unsigned visitCount,
-                                      const void *symbolTag = nullptr) {
-    return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
-  }
+  // const SymbolConjured* conjureSymbol(const Stmt *stmt,
+  //                                     const LocationContext *LCtx,
+  //                                     QualType type,
+  //                                     unsigned visitCount,
+  //                                     const void *symbolTag = nullptr) {
+  //   return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
+  // }
+
+  // const SymbolConjured* conjureSymbol(const Expr *expr,
+  //                                     const LocationContext *LCtx,
+  //                                     unsigned visitCount,
+  //                                     const void *symbolTag = nullptr) {
+  //   return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
+  // }
 
   /// Construct an SVal representing '0' for the specified type.
   DefinedOrUnknownSVal makeZeroVal(QualType type);
@@ -198,33 +206,38 @@ class SValBuilder {
   /// The advantage of symbols derived/built from other symbols is that we
   /// preserve the relation between related(or even equivalent) expressions, so
   /// conjured symbols should be used sparingly.
-  DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
-                                        const Expr *expr,
-                                        const LocationContext *LCtx,
-                                        unsigned count);
-  DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
-                                        const LocationContext *LCtx,
-                                        QualType type, unsigned count);
-  DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
-                                        const LocationContext *LCtx,
-                                        QualType type,
-                                        unsigned visitCount);
-
-  /// Conjure a symbol representing heap allocated memory region.
-  ///
-  /// Note, the expression should represent a location.
-  DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
-                                       const LocationContext *LCtx,
-                                       unsigned Count);
-
-  /// Conjure a symbol representing heap allocated memory region.
-  ///
-  /// Note, now, the expression *doesn't* need to represent a location.
-  /// But the type need to!
-  DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
-                                       const LocationContext *LCtx,
-                                       QualType type, unsigned Count);
-
+  // DefinedOrUnknownSVal
+  // conjureSymbolVal(const void *symbolTag,
+  //                  const CFGBlock::ConstCFGElementRef elemRef,
+  //                  const LocationContext *LCtx, unsigned count);
+  DefinedOrUnknownSVal
+  conjureSymbolVal(const void *symbolTag,
+                   const CFGBlock::ConstCFGElementRef elemRef,
+                   const LocationContext *LCtx, QualType type, unsigned count);
+  DefinedOrUnknownSVal
+  conjureSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
+                   const LocationContext *LCtx, QualType type,
+                   unsigned visitCount);
+
+  // /// Conjure a symbol representing heap allocated memory region.
+  // ///
+  // /// Note, the expression should represent a location.
+  // DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
+  //                                      const LocationContext *LCtx,
+  //                                      unsigned Count);
+
+  // /// Conjure a symbol representing heap allocated memory region.
+  // ///
+  // /// Note, now, the expression *doesn't* need to represent a location.
+  // /// But the type need to!
+  // DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
+  //                                      const LocationContext *LCtx,
+  //                                      QualType type, unsigned Count);
+
+  DefinedSVal
+  getConjuredHeapSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
+                           const LocationContext *LCtx, QualType type,
+                           unsigned Count);
   /// Create an SVal representing the result of an alloca()-like call, that is,
   /// an AllocaRegion on the stack.
   ///
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index cbbea1b56bb40..10b2b91036f2f 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
@@ -85,12 +86,14 @@ class SymbolConjured : public SymbolData {
   unsigned Count;
   const LocationContext *LCtx;
   const void *SymbolTag;
+  const CFGBlock::ConstCFGElementRef ElemRef;
 
   friend class SymExprAllocator;
-  SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
-                 QualType t, unsigned count, const void *symbolTag)
-      : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
-        LCtx(lctx), SymbolTag(symbolTag) {
+  SymbolConjured(SymbolID sym, CFGBlock::ConstCFGElementRef elemRef,
+                 const LocationContext *lctx, QualType t, unsigned count,
+                 const void *symbolTag)
+      : SymbolData(SymbolConjuredKind, sym), S(nullptr), T(t), Count(count),
+        LCtx(lctx), SymbolTag(symbolTag), ElemRef(elemRef) {
     // FIXME: 's' might be a nullptr if we're conducting invalidation
     // that was caused by a destructor call on a temporary object,
     // which has no statement associated with it.
@@ -102,7 +105,12 @@ class SymbolConjured : public SymbolData {
 
 public:
   /// It might return null.
-  const Stmt *getStmt() const { return S; }
+  const Stmt *getStmt() const {
+    if (auto Stmt = ElemRef->getAs<CFGStmt>()) {
+      return Stmt->getStmt();
+    }
+    return S;
+  }
   unsigned getCount() const { return Count; }
   /// It might return null.
   const void *getTag() const { return SymbolTag; }
@@ -113,11 +121,13 @@ class SymbolConjured : public SymbolData {
 
   void dumpToStream(raw_ostream &os) const override;
 
-  static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
+  static void Profile(llvm::FoldingSetNodeID &profile,
+                      const CFGBlock::ConstCFGElementRef ElemRef,
                       const LocationContext *LCtx, QualType T, unsigned Count,
                       const void *SymbolTag) {
     profile.AddInteger((unsigned)SymbolConjuredKind);
-    profile.AddPointer(S);
+    // profile.Add(ElemRef);
+    // profile.AddPointer(S);
     profile.AddPointer(LCtx);
     profile.Add(T);
     profile.AddInteger(Count);
@@ -125,7 +135,7 @@ class SymbolConjured : public SymbolData {
   }
 
   void Profile(llvm::FoldingSetNodeID& profile) override {
-    Profile(profile, S, LCtx, T, Count, SymbolTag);
+    Profile(profile, ElemRef, LCtx, T, Count, SymbolTag);
   }
 
   // Implement isa<T> support.
@@ -533,20 +543,28 @@ class SymbolManager {
   template <typename SymExprT, typename... Args>
   const SymExprT *acquire(Args &&...args);
 
-  const SymbolConjured *conjureSymbol(const Stmt *E,
-                                      const LocationContext *LCtx, QualType T,
-                                      unsigned VisitCount,
-                                      const void *SymbolTag = nullptr) {
-    return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
-  }
+  // const SymbolConjured *conjureSymbol(const Stmt *E,
+  //                                     const LocationContext *LCtx, QualType
+  //                                     T, unsigned VisitCount, const void
+  //                                     *SymbolTag = nullptr) {
+  //   return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
+  // }
 
-  const SymbolConjured* conjureSymbol(const Expr *E,
-                                      const LocationContext *LCtx,
-                                      unsigned VisitCount,
-                                      const void *SymbolTag = nullptr) {
-    return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
+  const SymbolConjured *
+  conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
+                const LocationContext *LCtx, QualType T, unsigned VisitCount,
+                const void *SymbolTag = nullptr) {
+
+    return acquire<SymbolConjured>(ElemRef, LCtx, T, VisitCount, SymbolTag);
   }
 
+  // const SymbolConjured* conjureSymbol(const Expr *E,
+  //                                     const LocationContext *LCtx,
+  //                                     unsigned VisitCount,
+  //                                     const void *SymbolTag = nullptr) {
+  //   return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
+  // }
+
   QualType getType(const SymExpr *SE) const {
     return SE->getType();
   }
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 318fa3c1caf06..6c569e4ccadbe 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -437,8 +437,8 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
   // values inside Reg would be correct.
   SVal InitVal = State->getSVal(Init, LC);
   if (InitVal.isUnknown()) {
-    InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(),
-                                                currBldrCtx->blockCount());
+    InitVal = getSValBuilder().conjureSymbolVal(
+        getCFGElementRef(), LC, Init->getType(), currBldrCtx->blockCount());
     State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
 
     // Then we'd need to take the value that certainly exists and bind it
@@ -447,7 +447,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
       // Try to recover some path sensitivity in case we couldn't
       // compute the value.
       InitValWithAdjustments = getSValBuilder().conjureSymbolVal(
-          Result, LC, InitWithAdjustments->getType(),
+          getCFGElementRef(), LC, InitWithAdjustments->getType(),
           currBldrCtx->blockCount());
     }
     State =
@@ -1213,9 +1213,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
         // If we fail to get the value for some reason, use a symbolic value.
         if (InitVal.isUnknownOrUndef()) {
           SValBuilder &SVB = getSValBuilder();
-          InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
-                                         Field->getType(),
-                                         currBldrCtx->blockCount());
+          InitVal =
+              SVB.conjureSymbolVal(getCFGElementRef(), stackFrame,
+                                   Field->getType(), currBldrCtx->blockCount());
         }
       } else {
         InitVal = State->getSVal(BMI->getInit(), stackFrame);
@@ -2042,9 +2042,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 
       for (const auto N : preVisit) {
         const LocationContext *LCtx = N->getLocationContext();
-        SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
-                                                   resultType,
-                                                   currBldrCtx->blockCount());
+        SVal result =
+            svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                         resultType, currBldrCtx->blockCount());
         ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
 
         // Escape pointers passed into the list, unless it's an ObjC boxed
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 1061dafbb2473..169983605f5f0 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -12,6 +12,7 @@
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include <optional>
@@ -26,13 +27,15 @@ using llvm::APSInt;
 /// (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, Expr* Expression, SValBuilder &svalBuilder,
-    unsigned Count, const LocationContext *LCtx) {
-  QualType Ty = Expression->getType();
+static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
+                                          CFGBlock::ConstCFGElementRef elemRef,
+                                          QualType Ty, SValBuilder &svalBuilder,
+                                          unsigned Count,
+                                          const LocationContext *LCtx) {
+  // QualType Ty = Expression->getType();
   if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
       Symbol.isUnknown()) {
-    return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count);
+    return svalBuilder.conjureSymbolVal(elemRef, LCtx, Ty, Count);
   }
   return Symbol;
 }
@@ -65,8 +68,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
       // FIXME: Handle structs.
       if (RightV.isUnknown()) {
         unsigned Count = currBldrCtx->blockCount();
-        RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
-                                              Count);
+        RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                              B->getRHS()->getType(), Count);
       }
       // Simulate the effects of a "store":  bind the value of the RHS
       // to the L-Value represented by the LHS.
@@ -84,9 +87,11 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
         // SymSymExpr.
         unsigned Count = currBldrCtx->blockCount();
         RightV = conjureOffsetSymbolOnLocation(
-            RightV, LeftV, RHS, svalBuilder, Count, LCtx);
-        LeftV = conjureOffsetSymbolOnLocation(
-            LeftV, RightV, LHS, svalBuilder, Count, LCtx);
+            RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
+            Count, LCtx);
+        LeftV = conjureOffsetSymbolOnLocation(LeftV, RightV, getCFGElementRef(),
+                                              LHS->getType(), svalBuilder,
+                                              Count, LCtx);
       }
 
       // Although we don't yet model pointers-to-members, we do need to make
@@ -165,8 +170,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
         // 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(nullptr, B->getRHS(), LCtx, LTy,
-                                              currBldrCtx->blockCount());
+        LHSVal = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                              LTy, currBldrCtx->blockCount());
         // However, we need to convert the symbol to the computation type.
         Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
       } else {
@@ -459,9 +464,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
         } else {
           // If we don't know if the cast succeeded, conjure a new symbol.
           if (val.isUnknown()) {
-            DefinedOrUnknownSVal NewSym =
-              svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
-                                           currBldrCtx->blockCount());
+            DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
+                nullptr, getCFGElementRef(), LCtx, resultType,
+                currBldrCtx->blockCount());
             state = state->BindExpr(CastE, LCtx, NewSym);
           } else
             // Else, bind to the derived region value.
@@ -483,9 +488,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
 
         // Failed to cast or the result is unknown, fall back to conservative.
         if (val.isUnknown()) {
-          val =
-            svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
-                                         currBldrCtx->blockCount());
+          val = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                             resultType,
+                                             currBldrCtx->blockCount());
         }
         state = state->BindExpr(CastE, LCtx, val);
         Bldr.generateNode(CastE, Pred, state);
@@ -529,7 +534,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
         if (CastE->isGLValue())
           resultType = getContext().getPointerType(resultType);
         SVal result = svalBuilder.conjureSymbolVal(
-            /*symbolTag=*/nullptr, CastE, LCtx, resultType,
+            /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
             currBldrCtx->blockCount());
         state = state->BindExpr(CastE, LCtx, result);
         Bldr.generateNode(CastE, Pred, state);
@@ -621,8 +626,8 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
             Ty = getContext().getPointerType(Ty);
           }
 
-          InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
-                                                 currBldrCtx->blockCount());
+          InitVal = svalBuilder.conjureSymbolVal(
+              nullptr, getCFGElementRef(), LC, Ty, currBldrCtx->blockCount());
         }
 
 
@@ -839,8 +844,8 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
   }
 
   if (!hasValue)
-    V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
-                                     currBldrCtx->blockCount());
+    V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                     Ex->getType(), currBldrCtx->blockCount());
 
   // Generate a new node with the binding from the appropriate path.
   B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
@@ -1122,8 +1127,8 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
     // Conjure a new symbol if necessary to recover precision.
     if (Result.isUnknown()){
       DefinedOrUnknownSVal SymVal =
-        svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
-                                     currBldrCtx->blockCount());
+          svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                       U->getType(), currBldrCtx->blockCount());
       Result = SymVal;
 
       // If the value is a location, ++/-- should always preserve
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index f7020da2e6da2..0860402778826 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -235,8 +235,8 @@ SVal ExprEngine::computeObjectUnderConstruction(
         assert(RetE && "Void returns should not have a construction context");
         QualType ReturnTy = RetE->getType();
         QualType RegionTy = ACtx.getPointerType(ReturnTy);
-        return SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC, RegionTy,
-                                    currBldrCtx->blockCount());
+        return SVB.conjureSymbolVal(&TopLevelSymRegionTag, getCFGElementRef(),
+                                    SFC, RegionTy, currBldrCtx->blockCount());
       }
       llvm_unreachable("Unhandled return value construction context!");
     }
@@ -967,10 +967,11 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
   // a custom global allocator.
   if (symVal.isUnknown()) {
     if (IsStandardGlobalOpNewFunction)
-      symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
+      symVal = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,
+                                                    CNE->getType(), blockCount);
     else
-      symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
-                                            blockCount);
+      symVal = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+                                            CNE->getType(), blockCount);
   }
 
   CallEventManager &CEMgr = getStateManager().getCallEventManager();
@@ -1102,7 +1103,7 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
   }
 
   const LocationContext *LCtx = Pred->getLocationContext();
-  SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(),
+  SVal V = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, VD->getType(),
                                         currBldrCtx->blockCount());
   ProgramStateRef state = Pred->getState();
   state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 02facf786830d..7207e7950a5bf 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -800,7 +800,8 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
     // a regular unknown pointer.
     const auto *CNE = dyn_cast<CXXNewExpr>(E);
     if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
-      R = svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count);
+      R = svalBuilder.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
+                                               E->getType(), Count);
       const MemRegion *MR = R.getAsRegion()->StripCasts();
 
       // Store the extent of the allocated object(s).
@@ -824,7 +825,8 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
 
       State = setDynamicExtent(State, MR, Size.castAs<DefinedOrUnknownSVal>());
     } else {
-      R = svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+      R = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, ResultTy,
+                                       Count);
     }
   }
   return State->BindExpr(E, LCtx, R);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index 9426e0afd65a0..ac67b9e1dc301 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -45,8 +45,8 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
 /// for-loop iterator.
 static void populateObjCForDestinationSet(
     ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder,
-    const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV,
-    SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
+    const ObjCForCollectionStmt *S, const CFGBlock::ConstCFGElementRef elemRef,
+    SVal elementV, SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
     StmtNodeBuilder &Bldr, bool hasElements) {
 
   for (ExplodedNode *Pred : dstLocation) {
@@ -66,8 +66,8 @@ static void populateObjCForDestinationSet(
 
         SVal V;
         if (hasElements) {
-          SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
-                                               currBldrCtx->blockCount());
+          SymbolRef Sym =
+              SymMgr.conjureSymbol(elemRef, LCtx, T, currBldrCtx->blockCount());
           V = svalBuilder.makeLoc(Sym);
         } else {
           V = svalBuilder.makeIntVal(0, T);
@@ -110,6 +110,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
 
   const Stmt *elem = S->getElement();
   const Stmt *collection = S->getCollection();
+  const CFGBlock::ConstCFGElementRef elemRef = getCFGElementRef();
   ProgramStateRef state = Pred->getState();
   SVal collectionV = state->getSVal(collection, Pred->getLocationContext());
 
@@ -132,11 +133,12 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
     StmtNodeBuilder Bldr(dstLocation, Tmp, *currBldrCtx);
 
     if (!isContainerNull)
-      populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elem,
-                                    elementV, SymMgr, currBldrCtx, Bldr,
+      populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S,
+                                    elemRef, elementV, SymMgr, currBldrCtx,
+                                    Bldr,
                                     /*hasElements=*/true);
 
-    populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elem,
+    populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elemRef,
                                   elementV, SymMgr, currBldrCtx, Bldr,
                                   /*hasElements=*/false);
 
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 4f45b24be86c1..dd173a35cfd73 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -151,36 +151,35 @@ SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
   return nonloc::SymbolVal(sym);
 }
 
-DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
-                                                   const Expr *Ex,
-                                                   const LocationContext *LCtx,
-                                                   unsigned Count) {
-  QualType T = Ex->getType();
-
-  if (T->isNullPtrType())
-    return makeZeroVal(T);
-
-  // Compute the type of the result. If the expression is not an R-value, the
-  // result should be a location.
-  QualType ExType = Ex->getType();
-  if (Ex->isGLValue())
-    T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
-
-  return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
-}
+// DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
+//                                                    const Expr *Ex,
+//                                                    const LocationContext
+//                                                    *LCtx, unsigned Count) {
+//   QualType T = Ex->getType();
+//
+//   if (T->isNullPtrType())
+//     return makeZeroVal(T);
+//
+//   // Compute the type of the result. If the expression is not an R-value, the
+//   // result should be a location.
+//   QualType ExType = Ex->getType();
+//   if (Ex->isGLValue())
+//     T =
+//     LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
+//
+//   return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
+// }
 
-DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
-                                                   const Stmt *St,
-                                                   const LocationContext *LCtx,
-                                                   QualType type,
-                                                   unsigned count) {
+DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(
+    const void *symbolTag, const CFGBlock::ConstCFGElementRef elemRef,
+    const LocationContext *LCtx, QualType type, unsigned count) {
   if (type->isNullPtrType())
     return makeZeroVal(type);
 
   if (!SymbolManager::canSymbolicate(type))
     return UnknownVal();
 
-  SymbolRef sym = SymMgr.conjureSymbol(St, LCtx, type, count, symbolTag);
+  SymbolRef sym = SymMgr.conjureSymbol(elemRef, LCtx, type, count, symbolTag);
 
   if (Loc::isLocType(type))
     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
@@ -188,17 +187,17 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
   return nonloc::SymbolVal(sym);
 }
 
-DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
-                                                   const LocationContext *LCtx,
-                                                   QualType type,
-                                                   unsigned visitCount) {
+DefinedOrUnknownSVal
+SValBuilder::conjureSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
+                              const LocationContext *LCtx, QualType type,
+                              unsigned visitCount) {
   if (type->isNullPtrType())
     return makeZeroVal(type);
 
   if (!SymbolManager::canSymbolicate(type))
     return UnknownVal();
 
-  SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(elemRef, LCtx, type, visitCount);
 
   if (Loc::isLocType(type))
     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
@@ -206,17 +205,33 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
   return nonloc::SymbolVal(sym);
 }
 
-DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
-                                                  const LocationContext *LCtx,
-                                                  unsigned VisitCount) {
-  QualType T = E->getType();
-  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
-}
+// DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+//                                                   const LocationContext
+//                                                   *LCtx, unsigned VisitCount)
+//                                                   {
+//   QualType T = E->getType();
+//   return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+// }
+//
+// DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+//                                                   const LocationContext
+//                                                   *LCtx, QualType type,
+//                                                   unsigned VisitCount) {
+//   assert(Loc::isLocType(type));
+//   assert(SymbolManager::canSymbolicate(type));
+//   if (type->isNullPtrType()) {
+//     // makeZeroVal() returns UnknownVal only in case of FP number, which
+//     // is not the case.
+//     return makeZeroVal(type).castAs<DefinedSVal>();
+//   }
+//
+//   SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
+//   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
+// }
 
-DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
-                                                  const LocationContext *LCtx,
-                                                  QualType type,
-                                                  unsigned VisitCount) {
+DefinedSVal SValBuilder::getConjuredHeapSymbolVal(
+    const CFGBlock::ConstCFGElementRef elemRef, const LocationContext *LCtx,
+    QualType type, unsigned VisitCount) {
   assert(Loc::isLocType(type));
   assert(SymbolManager::canSymbolicate(type));
   if (type->isNullPtrType()) {
@@ -225,7 +240,7 @@ DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
     return makeZeroVal(type).castAs<DefinedSVal>();
   }
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(elemRef, LCtx, type, VisitCount);
   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
 }
 

>From 949f43ae158046ab3b7d160bde61c5d05122a8ba Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Fri, 21 Feb 2025 21:36:29 +0000
Subject: [PATCH 02/12] Convert more references

---
 .../Core/PathSensitive/CheckerContext.h       |  5 ++
 .../Checkers/ContainerModeling.cpp            | 33 +++++------
 clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 57 ++++++++++---------
 3 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 168983fd5cb68..02bd4a91961a9 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -151,6 +151,11 @@ class CheckerContext {
     return Pred->getSVal(S);
   }
 
+  /// Get the CFG Element Ref from the ExprEngine
+  CFGBlock::ConstCFGElementRef getCFGElementRef() const {
+    return Eng.getCFGElementRef();
+  }
+
   /// Returns true if the value of \p E is greater than or equal to \p
   /// Val under unsigned comparison
   bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 55ed809bfed6c..74a7b8e0f54ff 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -107,13 +107,13 @@ bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
 bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
 SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
 SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
-ProgramStateRef createContainerBegin(ProgramStateRef State,
+ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
                                      const MemRegion *Cont, const Expr *E,
                                      QualType T, const LocationContext *LCtx,
                                      unsigned BlockCount);
-ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
-                                   const Expr *E, QualType T,
-                                   const LocationContext *LCtx,
+ProgramStateRef createContainerEnd(CheckerContext &C, ProgramStateRef State,
+                                   const MemRegion *Cont, const Expr *E,
+                                   QualType T, const LocationContext *LCtx,
                                    unsigned BlockCount);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
                                  const ContainerData &CData);
@@ -260,8 +260,9 @@ void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
   auto State = C.getState();
   auto BeginSym = getContainerBegin(State, ContReg);
   if (!BeginSym) {
-    State = createContainerBegin(State, ContReg, CE, C.getASTContext().LongTy,
-                                 C.getLocationContext(), C.blockCount());
+    State =
+        createContainerBegin(C, State, ContReg, CE, C.getASTContext().LongTy,
+                             C.getLocationContext(), C.blockCount());
     BeginSym = getContainerBegin(State, ContReg);
   }
   State = setIteratorPosition(State, RetVal,
@@ -282,7 +283,7 @@ void ContainerModeling::handleEnd(CheckerContext &C, const Expr *CE,
   auto State = C.getState();
   auto EndSym = getContainerEnd(State, ContReg);
   if (!EndSym) {
-    State = createContainerEnd(State, ContReg, CE, C.getASTContext().LongTy,
+    State = createContainerEnd(C, State, ContReg, CE, C.getASTContext().LongTy,
                                C.getLocationContext(), C.blockCount());
     EndSym = getContainerEnd(State, ContReg);
   }
@@ -326,7 +327,7 @@ void ContainerModeling::handleAssignment(CheckerContext &C, SVal Cont,
           auto &SVB = C.getSValBuilder();
           // Then generate and assign a new "end" symbol for the new container.
           auto NewEndSym =
-              SymMgr.conjureSymbol(CE, C.getLocationContext(),
+              SymMgr.conjureSymbol(C.getCFGElementRef(), C.getLocationContext(),
                                    C.getASTContext().LongTy, C.blockCount());
           State = assumeNoOverflow(State, NewEndSym, 4);
           if (CData) {
@@ -844,7 +845,7 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
   return CDataPtr->getEnd();
 }
 
-ProgramStateRef createContainerBegin(ProgramStateRef State,
+ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
                                      const MemRegion *Cont, const Expr *E,
                                      QualType T, const LocationContext *LCtx,
                                      unsigned BlockCount) {
@@ -854,8 +855,8 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
     return State;
 
   auto &SymMgr = State->getSymbolManager();
-  const SymbolConjured *Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount,
-                                                   "begin");
+  const SymbolConjured *Sym =
+      SymMgr.conjureSymbol(C.getCFGElementRef(), LCtx, T, BlockCount, "begin");
   State = assumeNoOverflow(State, Sym, 4);
 
   if (CDataPtr) {
@@ -867,9 +868,9 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
   return setContainerData(State, Cont, CData);
 }
 
-ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
-                                   const Expr *E, QualType T,
-                                   const LocationContext *LCtx,
+ProgramStateRef createContainerEnd(CheckerContext &C, ProgramStateRef State,
+                                   const MemRegion *Cont, const Expr *E,
+                                   QualType T, const LocationContext *LCtx,
                                    unsigned BlockCount) {
   // Only create if it does not exist
   const auto *CDataPtr = getContainerData(State, Cont);
@@ -877,8 +878,8 @@ ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
     return State;
 
   auto &SymMgr = State->getSymbolManager();
-  const SymbolConjured *Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount,
-                                                  "end");
+  const SymbolConjured *Sym =
+      SymMgr.conjureSymbol(C.getCFGElementRef(), LCtx, T, BlockCount, "end");
   State = assumeNoOverflow(State, Sym, 4);
 
   if (CDataPtr) {
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 5a5a6948098e7..88aae1836d20b 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -19,6 +19,7 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/Basic/JsonSupport.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
@@ -473,11 +474,11 @@ class RegionStoreManager : public StoreManager {
   //===-------------------------------------------------------------------===//
   // Binding values to regions.
   //===-------------------------------------------------------------------===//
-  RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K, const Stmt *S,
-                                           unsigned Count,
-                                           const LocationContext *LCtx,
-                                           RegionBindingsRef B,
-                                           InvalidatedRegions *Invalidated);
+  RegionBindingsRef
+  invalidateGlobalRegion(MemRegion::Kind K,
+                         const CFGBlock::ConstCFGElementRef elemRef,
+                         unsigned Count, const LocationContext *LCtx,
+                         RegionBindingsRef B, InvalidatedRegions *Invalidated);
 
   StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values, const Stmt *S,
                              unsigned Count, const LocationContext *LCtx,
@@ -1044,7 +1045,7 @@ RegionStoreManager::removeSubRegionBindings(RegionBindingsConstRef B,
 namespace {
 class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
 {
-  const Stmt *S;
+  const CFGBlock::ConstCFGElementRef ElemRef;
   unsigned Count;
   const LocationContext *LCtx;
   InvalidatedSymbols &IS;
@@ -1053,14 +1054,16 @@ class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
   GlobalsFilterKind GlobalsFilter;
 public:
   InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
-                          RegionBindingsRef b, const Stmt *S, unsigned count,
-                          const LocationContext *lctx, InvalidatedSymbols &is,
+                          RegionBindingsRef b,
+                          const CFGBlock::ConstCFGElementRef elemRef,
+                          unsigned count, const LocationContext *lctx,
+                          InvalidatedSymbols &is,
                           RegionAndSymbolInvalidationTraits &ITraitsIn,
                           StoreManager::InvalidatedRegions *r,
                           GlobalsFilterKind GFK)
-      : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), S(S),
-        Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
-        GlobalsFilter(GFK) {}
+      : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
+        ElemRef(elemRef), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn),
+        Regions(r), GlobalsFilter(GFK) {}
 
   void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
   void VisitBinding(SVal V);
@@ -1193,7 +1196,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
     // Invalidate the region by setting its default value to
     // conjured symbol. The type of the symbol is irrelevant.
     DefinedOrUnknownSVal V =
-        svalBuilder.conjureSymbolVal(baseR, S, LCtx, Ctx.IntTy, Count);
+        svalBuilder.conjureSymbolVal(baseR, ElemRef, LCtx, Ctx.IntTy, Count);
     B = B.addBinding(baseR, BindingKey::Default, V);
     return;
   }
@@ -1215,7 +1218,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
     // Invalidate the region by setting its default value to
     // conjured symbol. The type of the symbol is irrelevant.
     DefinedOrUnknownSVal V =
-        svalBuilder.conjureSymbolVal(baseR, S, LCtx, Ctx.IntTy, Count);
+        svalBuilder.conjureSymbolVal(baseR, ElemRef, LCtx, Ctx.IntTy, Count);
     B = B.addBinding(baseR, BindingKey::Default, V);
     return;
   }
@@ -1283,13 +1286,13 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
   conjure_default:
       // Set the default value of the array to conjured symbol.
       DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(
-          baseR, S, LCtx, AT->getElementType(), Count);
+          baseR, ElemRef, LCtx, AT->getElementType(), Count);
       B = B.addBinding(baseR, BindingKey::Default, V);
       return;
   }
 
   DefinedOrUnknownSVal V =
-      svalBuilder.conjureSymbolVal(baseR, S, LCtx, T, Count);
+      svalBuilder.conjureSymbolVal(baseR, ElemRef, LCtx, T, Count);
   assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
   B = B.addBinding(baseR, BindingKey::Direct, V);
 }
@@ -1318,15 +1321,15 @@ bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
 }
 
 RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
-    MemRegion::Kind K, const Stmt *S, unsigned Count,
-    const LocationContext *LCtx, RegionBindingsRef B,
+    MemRegion::Kind K, const CFGBlock::ConstCFGElementRef elemRef,
+    unsigned Count, const LocationContext *LCtx, RegionBindingsRef B,
     InvalidatedRegions *Invalidated) {
   // Bind the globals memory space to a new symbol that we will use to derive
   // the bindings for all globals.
   const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
-  SVal V =
-      svalBuilder.conjureSymbolVal(/* symbolTag = */ (const void *)GS, S, LCtx,
-                                   /* type does not matter */ Ctx.IntTy, Count);
+  SVal V = svalBuilder.conjureSymbolVal(
+      /* symbolTag = */ (const void *)GS, elemRef, LCtx,
+      /* type does not matter */ Ctx.IntTy, Count);
 
   B = B.removeBinding(GS)
        .addBinding(BindingKey::Make(GS, BindingKey::Default), V);
@@ -1376,8 +1379,8 @@ StoreRef RegionStoreManager::invalidateRegions(
   }
 
   RegionBindingsRef B = getRegionBindings(store);
-  InvalidateRegionsWorker W(*this, StateMgr, B, S, Count, LCtx, IS, ITraits,
-                            Invalidated, GlobalsFilter);
+  InvalidateRegionsWorker W(*this, StateMgr, B, Call->getCFGElementRef(), Count,
+                            LCtx, IS, ITraits, Invalidated, GlobalsFilter);
 
   // Scan the bindings and generate the clusters.
   W.GenerateClusters();
@@ -1396,12 +1399,14 @@ StoreRef RegionStoreManager::invalidateRegions(
   // TODO: This could possibly be more precise with modules.
   switch (GlobalsFilter) {
   case GFK_All:
-    B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, S,
-                               Count, LCtx, B, Invalidated);
+    B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
+                               Call->getCFGElementRef(), Count, LCtx, B,
+                               Invalidated);
     [[fallthrough]];
   case GFK_SystemOnly:
-    B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, S, Count,
-                               LCtx, B, Invalidated);
+    B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
+                               Call->getCFGElementRef(), Count, LCtx, B,
+                               Invalidated);
     [[fallthrough]];
   case GFK_None:
     break;

>From bcd8b55078a905b1bbd00356bc839e5d0c475022 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Fri, 21 Feb 2025 22:21:21 +0000
Subject: [PATCH 03/12] Convert the checkers

---
 .../Core/PathSensitive/SValBuilder.h          |  8 ++---
 .../Core/PathSensitive/SymbolManager.h        |  9 +++--
 .../Checkers/CStringChecker.cpp               | 34 ++++++++++++-------
 .../StaticAnalyzer/Checkers/ErrnoModeling.cpp |  2 +-
 .../Checkers/ErrnoTesterChecker.cpp           |  3 +-
 .../lib/StaticAnalyzer/Checkers/Iterator.cpp  | 11 +++---
 clang/lib/StaticAnalyzer/Checkers/Iterator.h  |  9 ++---
 .../Checkers/IteratorModeling.cpp             | 29 +++++++++-------
 .../StaticAnalyzer/Checkers/MallocChecker.cpp |  6 ++--
 .../RetainCountChecker/RetainCountChecker.cpp |  4 +--
 .../Checkers/STLAlgorithmModeling.cpp         | 13 ++++---
 .../Checkers/SmartPtrModeling.cpp             |  8 ++---
 .../Checkers/StdLibraryFunctionsChecker.cpp   |  5 +--
 .../StaticAnalyzer/Checkers/StreamChecker.cpp |  3 +-
 .../Checkers/cert/InvalidPtrChecker.cpp       |  2 +-
 .../lib/StaticAnalyzer/Core/SymbolManager.cpp |  2 +-
 16 files changed, 85 insertions(+), 63 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 5b2887b0f9a86..6fb5f15822585 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -172,10 +172,10 @@ class SValBuilder {
 
   // Forwarding methods to SymbolManager.
 
-  const SymbolConjured *conjureSymbol(const CFGBlock::CFGElementRef ElemRef,
-                                      const LocationContext *LCtx,
-                                      QualType type, unsigned visitCount,
-                                      const void *symbolTag = nullptr) {
+  const SymbolConjured *
+  conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
+                const LocationContext *LCtx, QualType type, unsigned visitCount,
+                const void *symbolTag = nullptr) {
     return SymMgr.conjureSymbol(ElemRef, LCtx, type, visitCount, symbolTag);
   }
 
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 10b2b91036f2f..4e24c9a81ae1f 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -81,19 +81,18 @@ class SymbolRegionValue : public SymbolData {
 /// A symbol representing the result of an expression in the case when we do
 /// not know anything about what the expression is.
 class SymbolConjured : public SymbolData {
-  const Stmt *S;
+  const CFGBlock::ConstCFGElementRef ElemRef;
   QualType T;
   unsigned Count;
   const LocationContext *LCtx;
   const void *SymbolTag;
-  const CFGBlock::ConstCFGElementRef ElemRef;
 
   friend class SymExprAllocator;
   SymbolConjured(SymbolID sym, CFGBlock::ConstCFGElementRef elemRef,
                  const LocationContext *lctx, QualType t, unsigned count,
                  const void *symbolTag)
-      : SymbolData(SymbolConjuredKind, sym), S(nullptr), T(t), Count(count),
-        LCtx(lctx), SymbolTag(symbolTag), ElemRef(elemRef) {
+      : SymbolData(SymbolConjuredKind, sym), ElemRef(elemRef), T(t),
+        Count(count), LCtx(lctx), SymbolTag(symbolTag) {
     // FIXME: 's' might be a nullptr if we're conducting invalidation
     // that was caused by a destructor call on a temporary object,
     // which has no statement associated with it.
@@ -109,7 +108,7 @@ class SymbolConjured : public SymbolData {
     if (auto Stmt = ElemRef->getAs<CFGStmt>()) {
       return Stmt->getStmt();
     }
-    return S;
+    return nullptr;
   }
   unsigned getCount() const { return Count; }
   /// It might return null.
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 39dcaf02dbe25..ea3b815a95bc1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1515,7 +1515,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
       // conjure a return value for later.
       if (lastElement.isUnknown())
         lastElement = C.getSValBuilder().conjureSymbolVal(
-            nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
+            nullptr, Call.getCFGElementRef(), LCtx,
+            Call.getOriginExpr()->getType(), C.blockCount());
 
       // The byte after the last byte copied is the return value.
       state = state->BindExpr(Call.getOriginExpr(), LCtx, lastElement);
@@ -1665,8 +1666,9 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
     State = CheckBufferAccess(C, State, Left, Size, AccessKind::read, CK);
     if (State) {
       // The return value is the comparison result, which we don't know.
-      SVal CmpV = Builder.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
-                                           C.blockCount());
+      SVal CmpV = Builder.conjureSymbolVal(
+          nullptr, Call.getCFGElementRef(), LCtx,
+          Call.getOriginExpr()->getType(), C.blockCount());
       State = State->BindExpr(Call.getOriginExpr(), LCtx, CmpV);
       C.addTransition(State);
     }
@@ -1770,7 +1772,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
       // All we know is the return value is the min of the string length
       // and the limit. This is better than nothing.
       result = C.getSValBuilder().conjureSymbolVal(
-          nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
+          nullptr, Call.getCFGElementRef(), LCtx,
+          Call.getOriginExpr()->getType(), C.blockCount());
       NonLoc resultNL = result.castAs<NonLoc>();
 
       if (strLengthNL) {
@@ -1794,7 +1797,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
     // value, so it can be used in constraints, at least.
     if (result.isUnknown()) {
       result = C.getSValBuilder().conjureSymbolVal(
-          nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
+          nullptr, Call.getCFGElementRef(), LCtx,
+          Call.getOriginExpr()->getType(), C.blockCount());
     }
   }
 
@@ -2261,8 +2265,9 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
     // If this is a stpcpy-style copy, but we were unable to check for a buffer
     // overflow, we still need a result. Conjure a return value.
     if (ReturnEnd && Result.isUnknown()) {
-      Result = svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
-                                            C.blockCount());
+      Result = svalBuilder.conjureSymbolVal(
+          nullptr, Call.getCFGElementRef(), LCtx,
+          Call.getOriginExpr()->getType(), C.blockCount());
     }
   }
   // Set the return value.
@@ -2361,8 +2366,9 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
   const StringLiteral *RightStrLiteral =
       getCStringLiteral(C, state, Right.Expression, RightVal);
   bool canComputeResult = false;
-  SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(),
-                                                LCtx, C.blockCount());
+  SVal resultVal = svalBuilder.conjureSymbolVal(
+      nullptr, Call.getCFGElementRef(), LCtx, Call.getOriginExpr()->getType(),
+      C.blockCount());
 
   if (LeftStrLiteral && RightStrLiteral) {
     StringRef LeftStrRef = LeftStrLiteral->getString();
@@ -2469,14 +2475,15 @@ void CStringChecker::evalStrsep(CheckerContext &C,
     // further along in the same string, or NULL if there are no more tokens.
     State =
         State->bindLoc(*SearchStrLoc,
-                       SVB.conjureSymbolVal(getTag(), Call.getOriginExpr(),
+                       SVB.conjureSymbolVal(getTag(), Call.getCFGElementRef(),
                                             LCtx, CharPtrTy, C.blockCount()),
                        LCtx);
   } else {
     assert(SearchStrVal.isUnknown());
     // Conjure a symbolic value. It's the best we can do.
-    Result = SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
-                                  C.blockCount());
+    Result =
+        SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
+                             Call.getOriginExpr()->getType(), C.blockCount());
   }
 
   // Set the return value, and finish.
@@ -2520,7 +2527,8 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
   SValBuilder &SVB = C.getSValBuilder();
 
   SVal ResultVal =
-      SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
+      SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
+                           Call.getOriginExpr()->getType(), C.blockCount());
   State = State->BindExpr(Call.getOriginExpr(), LCtx, ResultVal);
 
   C.addTransition(State);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
index 6ffc05f06742b..cc8f1dd44b7e4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -124,7 +124,7 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
     // of the data member `ErrnoDecl` of the singleton `ErrnoModeling` checker
     // object.
     const SymbolConjured *Sym = SVB.conjureSymbol(
-        nullptr, C.getLocationContext(),
+        C.getCFGElementRef(), C.getLocationContext(),
         ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl);
 
     // The symbolic region is untyped, create a typed sub-region in it.
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
index 6076a6bc78973..b47787d59fc62 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
@@ -131,7 +131,8 @@ void ErrnoTesterChecker::evalSetErrnoIfErrorRange(CheckerContext &C,
   ProgramStateRef StateFailure = State->BindExpr(
       Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
   DefinedOrUnknownSVal ErrnoVal = SVB.conjureSymbolVal(
-      nullptr, Call.getOriginExpr(), C.getLocationContext(), C.blockCount());
+      nullptr, Call.getCFGElementRef(), C.getLocationContext(),
+      Call.getOriginExpr()->getType(), C.blockCount());
   StateFailure = StateFailure->assume(ErrnoVal, true);
   assert(StateFailure && "Failed to assume on an initial value.");
   StateFailure =
diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index ba561ddebdb69..31fdf58f6ba1e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Iterator.h"
+#include "clang/Analysis/CFG.h"
 
 namespace clang {
 namespace ento {
@@ -206,15 +207,15 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
   return nullptr;
 }
 
-ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
-                                       const MemRegion *Cont, const Stmt *S,
-                                       const LocationContext *LCtx,
-                                       unsigned blockCount) {
+ProgramStateRef
+createIteratorPosition(ProgramStateRef State, SVal Val, const MemRegion *Cont,
+                       const CFGBlock::ConstCFGElementRef ElemRef,
+                       const LocationContext *LCtx, unsigned blockCount) {
   auto &StateMgr = State->getStateManager();
   auto &SymMgr = StateMgr.getSymbolManager();
   auto &ACtx = StateMgr.getContext();
 
-  auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
+  auto Sym = SymMgr.conjureSymbol(ElemRef, LCtx, ACtx.LongTy, blockCount);
   State = assumeNoOverflow(State, Sym, 4);
   return setIteratorPosition(State, Val,
                              IteratorPosition::getPosition(Cont, Sym));
diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.h b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
index 46de8ea01d77b..dbae7da9cac22 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.h
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ITERATOR_H
 
+#include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
@@ -164,10 +165,10 @@ const ContainerData *getContainerData(ProgramStateRef State,
 const IteratorPosition *getIteratorPosition(ProgramStateRef State, SVal Val);
 ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
                                     const IteratorPosition &Pos);
-ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
-                                       const MemRegion *Cont, const Stmt *S,
-                                       const LocationContext *LCtx,
-                                       unsigned blockCount);
+ProgramStateRef
+createIteratorPosition(ProgramStateRef State, SVal Val, const MemRegion *Cont,
+                       const CFGBlock::ConstCFGElementRef ElemRef,
+                       const LocationContext *LCtx, unsigned blockCount);
 ProgramStateRef advancePosition(ProgramStateRef State, SVal Iter,
                                 OverloadedOperatorKind Op, SVal Distance);
 ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index d4ce73b03acb8..380991f10f499 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -99,7 +99,8 @@ class IteratorModeling
                                  const Expr *OrigExpr,
                                  const AdvanceFn *Handler) const;
 
-  void handleComparison(CheckerContext &C, const Expr *CE, SVal RetVal,
+  void handleComparison(CheckerContext &C, const Expr *CE,
+                        const CFGBlock::ConstCFGElementRef ElemRef, SVal RetVal,
                         SVal LVal, SVal RVal, OverloadedOperatorKind Op) const;
   void processComparison(CheckerContext &C, ProgramStateRef State,
                          SymbolRef Sym1, SymbolRef Sym2, SVal RetVal,
@@ -271,7 +272,7 @@ void IteratorModeling::checkPostStmt(const BinaryOperator *BO,
 
   if (isSimpleComparisonOperator(BO->getOpcode())) {
     SVal Result = State->getSVal(BO, C.getLocationContext());
-    handleComparison(C, BO, Result, LVal, RVal,
+    handleComparison(C, BO, C.getCFGElementRef(), Result, LVal, RVal,
                      BinaryOperator::getOverloadedOperator(OK));
   } else if (isRandomIncrOrDecrOperator(OK)) {
     // In case of operator+ the iterator can be either on the LHS (eg.: it + 1),
@@ -355,13 +356,15 @@ IteratorModeling::handleOverloadedOperator(CheckerContext &C,
         return;
 
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleComparison(C, OrigExpr, Call.getReturnValue(),
-                         InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
+        handleComparison(C, OrigExpr, Call.getCFGElementRef(),
+                         Call.getReturnValue(), InstCall->getCXXThisVal(),
+                         Call.getArgSVal(0), Op);
         return;
       }
 
-      handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
-                         Call.getArgSVal(1), Op);
+      handleComparison(C, OrigExpr, Call.getCFGElementRef(),
+                       Call.getReturnValue(), Call.getArgSVal(0),
+                       Call.getArgSVal(1), Op);
       return;
     } else if (isRandomIncrOrDecrOperator(Op)) {
       const auto *OrigExpr = Call.getOriginExpr();
@@ -443,9 +446,10 @@ IteratorModeling::handleAdvanceLikeFunction(CheckerContext &C,
   }
 }
 
-void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
-                                        SVal RetVal, SVal LVal, SVal RVal,
-                                        OverloadedOperatorKind Op) const {
+void IteratorModeling::handleComparison(
+    CheckerContext &C, const Expr *CE,
+    const CFGBlock::ConstCFGElementRef ElemRef, SVal RetVal, SVal LVal,
+    SVal RVal, OverloadedOperatorKind Op) const {
   // Record the operands and the operator of the comparison for the next
   // evalAssume, if the result is a symbolic expression. If it is a concrete
   // value (only one branch is possible), then transfer the state between
@@ -467,7 +471,7 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
   SymbolRef Sym;
   if (!LPos || !RPos) {
     auto &SymMgr = C.getSymbolManager();
-    Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
+    Sym = SymMgr.conjureSymbol(ElemRef, C.getLocationContext(),
                                C.getASTContext().LongTy, C.blockCount());
     State = assumeNoOverflow(State, Sym, 4);
   }
@@ -494,7 +498,7 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
     auto &SymMgr = C.getSymbolManager();
     auto *LCtx = C.getLocationContext();
     RetVal = nonloc::SymbolVal(SymMgr.conjureSymbol(
-        CE, LCtx, C.getASTContext().BoolTy, C.blockCount()));
+        ElemRef, LCtx, C.getASTContext().BoolTy, C.blockCount()));
     State = State->BindExpr(CE, LCtx, RetVal);
   }
 
@@ -688,7 +692,8 @@ void IteratorModeling::assignToContainer(CheckerContext &C, const Expr *CE,
 
   auto State = C.getState();
   const auto *LCtx = C.getLocationContext();
-  State = createIteratorPosition(State, RetVal, Cont, CE, LCtx, C.blockCount());
+  State = createIteratorPosition(State, RetVal, Cont, C.getCFGElementRef(),
+                                 LCtx, C.blockCount());
 
   C.addTransition(State);
 }
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 0d1213ddf8b01..ebd7f1a726b09 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1833,8 +1833,10 @@ ProgramStateRef MallocChecker::MallocBindRetVal(CheckerContext &C,
   unsigned Count = C.blockCount();
   SValBuilder &SVB = C.getSValBuilder();
   const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
-  DefinedSVal RetVal = isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
-                                : SVB.getConjuredHeapSymbolVal(CE, LCtx, Count);
+  DefinedSVal RetVal =
+      isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
+               : SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
+                                              CE->getType(), Count);
   return State->BindExpr(CE, C.getLocationContext(), RetVal);
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index cc1ced7358710..939a8544e28b7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -931,8 +931,8 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
     if (RetVal.isUnknown() ||
         (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
       SValBuilder &SVB = C.getSValBuilder();
-      RetVal =
-          SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
+      RetVal = SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
+                                    ResultTy, C.blockCount());
     }
 
     // Bind the value.
diff --git a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
index e037719b90298..f19ef750cae8c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
@@ -132,7 +132,8 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
   auto &SVB = C.getSValBuilder();
   const auto *LCtx = C.getLocationContext();
 
-  SVal RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
+  SVal RetVal = SVB.conjureSymbolVal(nullptr, C.getCFGElementRef(), LCtx,
+                                     CE->getType(), C.blockCount());
   SVal Param = State->getSVal(CE->getArg(paramNum), LCtx);
 
   auto StateFound = State->BindExpr(CE, LCtx, RetVal);
@@ -143,8 +144,9 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
   // FIXME: Reverse iterators
   const auto *Pos = getIteratorPosition(State, Param);
   if (Pos) {
-    StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
-                                        CE, LCtx, C.blockCount());
+    StateFound =
+        createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
+                               C.getCFGElementRef(), LCtx, C.blockCount());
     const auto *NewPos = getIteratorPosition(StateFound, RetVal);
     assert(NewPos && "Failed to create new iterator position.");
 
@@ -165,8 +167,9 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
   // FIXME: Reverse iterators
   Pos = getIteratorPosition(State, Param);
   if (Pos) {
-    StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
-                                        CE, LCtx, C.blockCount());
+    StateFound =
+        createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
+                               C.getCFGElementRef(), LCtx, C.blockCount());
     const auto *NewPos = getIteratorPosition(StateFound, RetVal);
     assert(NewPos && "Failed to create new iterator position.");
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index 321388ad857f4..32f8946ee1c57 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -306,7 +306,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
       return false;
 
     const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
-        Call.getOriginExpr(), C.getLocationContext(),
+        Call.getCFGElementRef(), C.getLocationContext(),
         getPointerTypeFromTemplateArg(Call, C), C.blockCount());
 
     const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
@@ -442,8 +442,8 @@ std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
   const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
   if (Ptr)
     return {*Ptr, State};
-  auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(),
-                                                 Type, C.blockCount());
+  auto Val = C.getSValBuilder().conjureSymbolVal(
+      C.getCFGElementRef(), C.getLocationContext(), Type, C.blockCount());
   State = State->set<TrackedRegionMap>(ThisRegion, Val);
   return {Val, State};
 }
@@ -853,7 +853,7 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
 
     const LocationContext *LC = C.getLocationContext();
     InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
-        CallExpr, LC, InnerPointerType, C.blockCount());
+        Call.getCFGElementRef(), LC, InnerPointerType, C.blockCount());
     State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
   }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 356d63e3e8b80..354797a3325d6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -585,7 +585,7 @@ class StdLibraryFunctionsChecker
                           CheckerContext &C) const override {
       SValBuilder &SVB = C.getSValBuilder();
       NonLoc ErrnoSVal =
-          SVB.conjureSymbolVal(&Tag, Call.getOriginExpr(),
+          SVB.conjureSymbolVal(&Tag, Call.getCFGElementRef(),
                                C.getLocationContext(), C.getASTContext().IntTy,
                                C.blockCount())
               .castAs<NonLoc>();
@@ -1479,7 +1479,8 @@ bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
     const LocationContext *LC = C.getLocationContext();
     const auto *CE = cast<CallExpr>(Call.getOriginExpr());
     SVal V = C.getSValBuilder().conjureSymbolVal(
-        CE, LC, CE->getType().getCanonicalType(), C.blockCount());
+        Call.getCFGElementRef(), LC, CE->getType().getCanonicalType(),
+        C.blockCount());
     State = State->BindExpr(CE, LC, V);
 
     C.addTransition(State);
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 80969ce664530..77671b567e613 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -229,7 +229,8 @@ DefinedSVal makeRetVal(CheckerContext &C, const CallExpr *CE) {
 
   const LocationContext *LCtx = C.getLocationContext();
   return C.getSValBuilder()
-      .conjureSymbolVal(nullptr, CE, LCtx, C.blockCount())
+      .conjureSymbolVal(nullptr, C.getCFGElementRef(), LCtx, CE->getType(),
+                        C.blockCount())
       .castAs<DefinedSVal>();
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
index fefe846b6911f..044f9ba61113b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
@@ -207,7 +207,7 @@ void InvalidPtrChecker::postPreviousReturnInvalidatingCall(
 
   // Function call will return a pointer to the new symbolic region.
   DefinedOrUnknownSVal RetVal = C.getSValBuilder().conjureSymbolVal(
-      CE, LCtx, CE->getType(), C.blockCount());
+      Call.getCFGElementRef(), LCtx, CE->getType(), C.blockCount());
   State = State->BindExpr(CE, LCtx, RetVal);
 
   const auto *SymRegOfRetVal =
diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index a4648f5922ef1..d24b98161b4d8 100644
--- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -82,7 +82,7 @@ void UnarySymExpr::dumpToStream(raw_ostream &os) const {
 
 void SymbolConjured::dumpToStream(raw_ostream &os) const {
   os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
-  if (S)
+  if (const auto *S = getStmt())
     os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
   else
     os << ", no stmt";

>From d1cd025c51841e93da842ca53a72733684c7ee36 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sat, 22 Feb 2025 10:25:58 +0000
Subject: [PATCH 04/12] Add Profile for CFGElementRef

---
 clang/include/clang/Analysis/CFG.h                           | 5 +++++
 .../clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h  | 3 +--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index a7ff38c786a8f..3c0582d648f01 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -695,6 +695,11 @@ class CFGBlock {
     void dump() const {
       dumpToStream(llvm::errs());
     }
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      ID.AddPointer(Parent);
+      ID.AddInteger(Index);
+    }
   };
 
   template <bool IsReverse, bool IsConst> class ElementRefIterator {
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 4e24c9a81ae1f..2b74e61ad2089 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -125,8 +125,7 @@ class SymbolConjured : public SymbolData {
                       const LocationContext *LCtx, QualType T, unsigned Count,
                       const void *SymbolTag) {
     profile.AddInteger((unsigned)SymbolConjuredKind);
-    // profile.Add(ElemRef);
-    // profile.AddPointer(S);
+    profile.Add(ElemRef);
     profile.AddPointer(LCtx);
     profile.Add(T);
     profile.AddInteger(Count);

>From da8bfb8f403be544dcf5af1477a4e484faa4078d Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sat, 22 Feb 2025 10:27:19 +0000
Subject: [PATCH 05/12] Add getter for CFGElementRef in SymbolConjured

---
 .../clang/StaticAnalyzer/Checkers/SValExplainer.h        | 9 +++++++--
 .../StaticAnalyzer/Core/PathSensitive/SymbolManager.h    | 6 ++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 519d2d5b3676b..2cb5e0123071f 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -113,8 +113,13 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
   }
 
   std::string VisitSymbolConjured(const SymbolConjured *S) {
-    return "symbol of type '" + S->getType().getAsString() +
-           "' conjured at statement '" + printStmt(S->getStmt()) + "'";
+    std::string Str;
+    llvm::raw_string_ostream OS(Str);
+    OS << "symbol of type '" + S->getType().getAsString() +
+              "' conjured at statement '";
+    S->getCFGElementRef()->dumpToStream(OS);
+    OS << "'";
+    return Str;
   }
 
   std::string VisitSymbolDerived(const SymbolDerived *S) {
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 2b74e61ad2089..05961f42c02c6 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -104,12 +104,18 @@ class SymbolConjured : public SymbolData {
 
 public:
   /// It might return null.
+  // TODO: Remove
   const Stmt *getStmt() const {
     if (auto Stmt = ElemRef->getAs<CFGStmt>()) {
       return Stmt->getStmt();
     }
     return nullptr;
   }
+
+  const CFGBlock::ConstCFGElementRef getCFGElementRef() const {
+    return ElemRef;
+  }
+
   unsigned getCount() const { return Count; }
   /// It might return null.
   const void *getTag() const { return SymbolTag; }

>From 6569f08e78387dedd1349ae2d2624b14be430a96 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sat, 22 Feb 2025 10:28:50 +0000
Subject: [PATCH 06/12] Pass along CFGElementRef in more calls

---
 .../Core/PathSensitive/LoopWidening.h         |  3 ++-
 .../Core/PathSensitive/ProgramState.h         | 14 ++++++++-----
 .../StaticAnalyzer/Core/PathSensitive/Store.h | 11 ++++++----
 .../Checkers/CStringChecker.cpp               |  4 ++--
 .../StaticAnalyzer/Checkers/ErrnoModeling.cpp |  2 +-
 .../StaticAnalyzer/Checkers/MallocChecker.cpp |  2 +-
 .../Checkers/SmartPtrModeling.cpp             |  2 +-
 .../StaticAnalyzer/Checkers/StreamChecker.cpp |  4 ++--
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp   |  2 +-
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  | 21 ++++++++++---------
 .../Core/ExprEngineCallAndReturn.cpp          |  2 +-
 .../lib/StaticAnalyzer/Core/LoopWidening.cpp  | 15 ++++++-------
 .../lib/StaticAnalyzer/Core/ProgramState.cpp  | 14 ++++++-------
 clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 18 ++++++++--------
 14 files changed, 62 insertions(+), 52 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
index e75228f92a8e5..1354fc058056d 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -27,7 +27,8 @@ namespace ento {
 /// by the loop body in any iteration.
 ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
                                     const LocationContext *LCtx,
-                                    unsigned BlockCount, const Stmt *LoopStmt);
+                                    unsigned BlockCount, const Stmt *LoopStmt,
+                                    const CFGBlock::ConstCFGElementRef ElemRef);
 
 } // end namespace ento
 } // end namespace clang
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index a20516b003c7d..80639fe6e3a6d 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 
+#include "clang/Analysis/CFG.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
@@ -313,7 +314,8 @@ class ProgramState : public llvm::FoldingSetNode {
   /// be triggered by this event.
   ///
   /// \param Regions the set of regions to be invalidated.
-  /// \param E the expression that caused the invalidation.
+  /// \param ElemRef \p CFGBlock::ConstCFGElementRef that caused the
+  /// invalidation.
   /// \param BlockCount The number of times the current basic block has been
   ///        visited.
   /// \param CausesPointerEscape the flag is set to true when the invalidation
@@ -325,16 +327,18 @@ class ProgramState : public llvm::FoldingSetNode {
   /// \param ITraits information about special handling for particular regions
   ///        or symbols.
   [[nodiscard]] ProgramStateRef
-  invalidateRegions(ArrayRef<const MemRegion *> Regions, const Stmt *S,
+  invalidateRegions(ArrayRef<const MemRegion *> Regions,
+                    const CFGBlock::ConstCFGElementRef ElemRef,
                     unsigned BlockCount, const LocationContext *LCtx,
                     bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
                     const CallEvent *Call = nullptr,
                     RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
 
   [[nodiscard]] ProgramStateRef
-  invalidateRegions(ArrayRef<SVal> Values, const Stmt *S, unsigned BlockCount,
-                    const LocationContext *LCtx, bool CausesPointerEscape,
-                    InvalidatedSymbols *IS = nullptr,
+  invalidateRegions(ArrayRef<SVal> Values,
+                    const CFGBlock::ConstCFGElementRef ElemRef,
+                    unsigned BlockCount, const LocationContext *LCtx,
+                    bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
                     const CallEvent *Call = nullptr,
                     RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
 
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 332855a3c9c45..217a6d33d48e0 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -14,13 +14,14 @@
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
 
 #include "clang/AST/Type.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
-#include "clang/Basic/LLVM.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -215,8 +216,9 @@ class StoreManager {
   ///
   /// \param[in] store The initial store.
   /// \param[in] Values The values to invalidate.
-  /// \param[in] S The current statement being evaluated. Used to conjure
-  ///   symbols to mark the values of invalidated regions.
+  /// \param[in] ElemRef The current \p CFGBlock::ConstCFGElementRef being
+  ///   evaluated. Used to conjure symbols to mark the values of invalidated
+  ///   regions.
   /// \param[in] Count The current block count. Used to conjure
   ///   symbols to mark the values of invalidated regions.
   /// \param[in] Call The call expression which will be used to determine which
@@ -233,7 +235,8 @@ class StoreManager {
   ///   even if they do not currently have bindings. Pass \c NULL if this
   ///   information will not be used.
   virtual StoreRef invalidateRegions(
-      Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
+      Store store, ArrayRef<SVal> Values,
+      const CFGBlock::ConstCFGElementRef ElemRef, unsigned Count,
       const LocationContext *LCtx, const CallEvent *Call,
       InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
       InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index ea3b815a95bc1..e54576be2ba04 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1299,8 +1299,8 @@ ProgramStateRef CStringChecker::invalidateBufferAux(
     RegionAndSymbolInvalidationTraits ITraits;
     bool CausesPointerEscape = InvalidationTraitOperations(ITraits, R);
 
-    return State->invalidateRegions(R, E, C.blockCount(), LCtx,
-                                    CausesPointerEscape, nullptr, nullptr,
+    return State->invalidateRegions(R, C.getCFGElementRef(), C.blockCount(),
+                                    LCtx, CausesPointerEscape, nullptr, nullptr,
                                     &ITraits);
   }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
index cc8f1dd44b7e4..ee7c0adf5aa9c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -260,7 +260,7 @@ ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
   const MemRegion *ErrnoR = State->get<ErrnoRegion>();
   if (!ErrnoR)
     return State;
-  State = State->invalidateRegions(ErrnoR, InvalE, C.blockCount(),
+  State = State->invalidateRegions(ErrnoR, C.getCFGElementRef(), C.blockCount(),
                                    C.getLocationContext(), false);
   if (!State)
     return nullptr;
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index ebd7f1a726b09..825bb977d7e60 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -2306,7 +2306,7 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
   // Assume that after memory is freed, it contains unknown values. This
   // conforts languages standards, since reading from freed memory is considered
   // UB and may result in arbitrary value.
-  State = State->invalidateRegions({location}, Call.getOriginExpr(),
+  State = State->invalidateRegions({location}, C.getCFGElementRef(),
                                    C.blockCount(), C.getLocationContext(),
                                    /*CausesPointerEscape=*/false,
                                    /*InvalidatedSymbols=*/nullptr);
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index 32f8946ee1c57..7ccb9210e4c58 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -530,7 +530,7 @@ bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
   if (!StreamThisRegion)
     return false;
   State =
-      State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
+      State->invalidateRegions({StreamThisRegion}, C.getCFGElementRef(),
                                C.blockCount(), C.getLocationContext(), false);
   State =
       State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 77671b567e613..49e332eb2a44a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -859,7 +859,7 @@ escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
     ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
   }
   return State->invalidateRegions(
-      EscapingVals, Call.getOriginExpr(), BlockCount, LCtx,
+      EscapingVals, Call.getCFGElementRef(), BlockCount, LCtx,
       /*CausesPointerEscape=*/false,
       /*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
 }
@@ -869,7 +869,7 @@ static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
                                   ArrayRef<unsigned int> EscapingArgs) {
   auto GetArgSVal = [&Call](int Idx) { return Call.getArgSVal(Idx); };
   auto EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
-  State = State->invalidateRegions(EscapingVals, Call.getOriginExpr(),
+  State = State->invalidateRegions(EscapingVals, C.getCFGElementRef(),
                                    C.blockCount(), C.getLocationContext(),
                                    /*CausesPointerEscape=*/false,
                                    /*InvalidatedSymbols=*/nullptr);
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index bb4a39f68280c..583315f4f3a90 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -280,7 +280,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
   // Invalidate designated regions using the batch invalidation API.
   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
   //  global variables.
-  return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
+  return Result->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
                                    BlockCount, getLocationContext(),
                                    /*CausedByPointerEscape*/ true,
                                    /*Symbols=*/nullptr, this, &ETraits);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 6c569e4ccadbe..480e27174a469 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -420,7 +420,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
       break;
     case SubobjectAdjustment::MemberPointerAdjustment:
       // FIXME: Unimplemented.
-      State = State->invalidateRegions(Reg, InitWithAdjustments,
+      State = State->invalidateRegions(Reg, getCFGElementRef(),
                                        currBldrCtx->blockCount(), LC, true,
                                        nullptr, nullptr, nullptr);
       return State;
@@ -2549,8 +2549,8 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
       return;
     // Widen.
     const LocationContext *LCtx = Pred->getLocationContext();
-    ProgramStateRef WidenedState =
-        getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
+    ProgramStateRef WidenedState = getWidenedLoopState(
+        Pred->getState(), LCtx, BlockCount, Term, getCFGElementRef());
     nodeBuilder.generateNode(WidenedState, Pred);
     return;
   }
@@ -3511,11 +3511,10 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
       ValuesToInvalidate.push_back(SubExprVal);
     }
 
-    State = State->invalidateRegions(ValuesToInvalidate, AE,
-                                    currBldrCtx->blockCount(),
-                                    LCtx,
-                                    /*CausedByPointerEscape*/true,
-                                    /*Symbols=*/nullptr);
+    State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
+                                     currBldrCtx->blockCount(), LCtx,
+                                     /*CausedByPointerEscape*/ true,
+                                     /*Symbols=*/nullptr);
 
     SVal ResultVal = UnknownVal();
     State = State->BindExpr(AE, LCtx, ResultVal);
@@ -3862,7 +3861,8 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
     assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
 
     if (std::optional<Loc> LV = X.getAs<Loc>())
-      state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
+      state = state->invalidateRegions(*LV, getCFGElementRef(),
+                                       currBldrCtx->blockCount(),
                                        Pred->getLocationContext(),
                                        /*CausedByPointerEscape=*/true);
   }
@@ -3872,7 +3872,8 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
     SVal X = state->getSVal(I, Pred->getLocationContext());
 
     if (std::optional<Loc> LV = X.getAs<Loc>())
-      state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
+      state = state->invalidateRegions(*LV, getCFGElementRef(),
+                                       currBldrCtx->blockCount(),
                                        Pred->getLocationContext(),
                                        /*CausedByPointerEscape=*/true);
   }
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 7207e7950a5bf..9bbfb3710f315 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -788,7 +788,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
     RegionAndSymbolInvalidationTraits ITraits;
     ITraits.setTrait(TargetR,
         RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
-    State = State->invalidateRegions(TargetR, E, Count, LCtx,
+    State = State->invalidateRegions(TargetR, getCFGElementRef(), Count, LCtx,
                                      /* CausesPointerEscape=*/false, nullptr,
                                      &Call, &ITraits);
 
diff --git a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 9e42801760622..617c8bf559a36 100644
--- a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -13,10 +13,11 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
 #include "clang/AST/AST.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
 
 using namespace clang;
 using namespace ento;
@@ -43,9 +44,10 @@ static const Expr *getLoopCondition(const Stmt *LoopStmt) {
 namespace clang {
 namespace ento {
 
-ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
-                                    const LocationContext *LCtx,
-                                    unsigned BlockCount, const Stmt *LoopStmt) {
+ProgramStateRef
+getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx,
+                    unsigned BlockCount, const Stmt *LoopStmt,
+                    const CFGBlock::ConstCFGElementRef ElemRef) {
 
   assert((isa<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(LoopStmt)));
 
@@ -93,9 +95,8 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
                      RegionAndSymbolInvalidationTraits::TK_PreserveContents);
   }
 
-  return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt),
-                                      BlockCount, LCtx, true, nullptr, nullptr,
-                                      &ITraits);
+  return PrevState->invalidateRegions(Regions, ElemRef, BlockCount, LCtx, true,
+                                      nullptr, nullptr, &ITraits);
 }
 
 } // end namespace ento
diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 34ab2388cbd2f..4d77ee31b5a43 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -148,21 +148,21 @@ typedef ArrayRef<const MemRegion *> RegionList;
 typedef ArrayRef<SVal> ValueList;
 
 ProgramStateRef ProgramState::invalidateRegions(
-    RegionList Regions, const Stmt *S, unsigned Count,
-    const LocationContext *LCtx, bool CausedByPointerEscape,
+    RegionList Regions, const CFGBlock::ConstCFGElementRef ElemRef,
+    unsigned Count, const LocationContext *LCtx, bool CausedByPointerEscape,
     InvalidatedSymbols *IS, const CallEvent *Call,
     RegionAndSymbolInvalidationTraits *ITraits) const {
   SmallVector<SVal, 8> Values;
   for (const MemRegion *Reg : Regions)
     Values.push_back(loc::MemRegionVal(Reg));
 
-  return invalidateRegions(Values, S, Count, LCtx, CausedByPointerEscape, IS,
-                           Call, ITraits);
+  return invalidateRegions(Values, ElemRef, Count, LCtx, CausedByPointerEscape,
+                           IS, Call, ITraits);
 }
 
 ProgramStateRef ProgramState::invalidateRegions(
-    ValueList Values, const Stmt *S, unsigned Count,
-    const LocationContext *LCtx, bool CausedByPointerEscape,
+    ValueList Values, const CFGBlock::ConstCFGElementRef ElemRef,
+    unsigned Count, const LocationContext *LCtx, bool CausedByPointerEscape,
     InvalidatedSymbols *IS, const CallEvent *Call,
     RegionAndSymbolInvalidationTraits *ITraits) const {
 
@@ -180,7 +180,7 @@ ProgramStateRef ProgramState::invalidateRegions(
   StoreManager::InvalidatedRegions TopLevelInvalidated;
   StoreManager::InvalidatedRegions Invalidated;
   const StoreRef &NewStore = Mgr.StoreMgr->invalidateRegions(
-      getStore(), Values, S, Count, LCtx, Call, *IS, *ITraits,
+      getStore(), Values, ElemRef, Count, LCtx, Call, *IS, *ITraits,
       &TopLevelInvalidated, &Invalidated);
 
   ProgramStateRef NewState = makeWithStore(NewStore);
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 88aae1836d20b..b4fe96f32ce8e 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -480,7 +480,8 @@ class RegionStoreManager : public StoreManager {
                          unsigned Count, const LocationContext *LCtx,
                          RegionBindingsRef B, InvalidatedRegions *Invalidated);
 
-  StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values, const Stmt *S,
+  StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values,
+                             const CFGBlock::ConstCFGElementRef ElemRef,
                              unsigned Count, const LocationContext *LCtx,
                              const CallEvent *Call, InvalidatedSymbols &IS,
                              RegionAndSymbolInvalidationTraits &ITraits,
@@ -1364,7 +1365,8 @@ void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
 }
 
 StoreRef RegionStoreManager::invalidateRegions(
-    Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
+    Store store, ArrayRef<SVal> Values,
+    const CFGBlock::ConstCFGElementRef ElemRef, unsigned Count,
     const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS,
     RegionAndSymbolInvalidationTraits &ITraits,
     InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
@@ -1379,8 +1381,8 @@ StoreRef RegionStoreManager::invalidateRegions(
   }
 
   RegionBindingsRef B = getRegionBindings(store);
-  InvalidateRegionsWorker W(*this, StateMgr, B, Call->getCFGElementRef(), Count,
-                            LCtx, IS, ITraits, Invalidated, GlobalsFilter);
+  InvalidateRegionsWorker W(*this, StateMgr, B, ElemRef, Count, LCtx, IS,
+                            ITraits, Invalidated, GlobalsFilter);
 
   // Scan the bindings and generate the clusters.
   W.GenerateClusters();
@@ -1400,13 +1402,11 @@ StoreRef RegionStoreManager::invalidateRegions(
   switch (GlobalsFilter) {
   case GFK_All:
     B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
-                               Call->getCFGElementRef(), Count, LCtx, B,
-                               Invalidated);
+                               ElemRef, Count, LCtx, B, Invalidated);
     [[fallthrough]];
   case GFK_SystemOnly:
-    B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
-                               Call->getCFGElementRef(), Count, LCtx, B,
-                               Invalidated);
+    B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, ElemRef,
+                               Count, LCtx, B, Invalidated);
     [[fallthrough]];
   case GFK_None:
     break;

>From f5aee84963cc9ec3ee9e2d5db42e699539e3ba96 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sat, 22 Feb 2025 10:36:59 +0000
Subject: [PATCH 07/12] Remove some unused code

---
 .../Core/PathSensitive/SValBuilder.h          | 36 ++-----------------
 .../Core/PathSensitive/SymbolManager.h        | 23 ------------
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 24 -------------
 .../lib/StaticAnalyzer/Core/SymbolManager.cpp |  6 ++--
 4 files changed, 4 insertions(+), 85 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 6fb5f15822585..c9fc8ae723258 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -179,21 +179,6 @@ class SValBuilder {
     return SymMgr.conjureSymbol(ElemRef, LCtx, type, visitCount, symbolTag);
   }
 
-  // const SymbolConjured* conjureSymbol(const Stmt *stmt,
-  //                                     const LocationContext *LCtx,
-  //                                     QualType type,
-  //                                     unsigned visitCount,
-  //                                     const void *symbolTag = nullptr) {
-  //   return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
-  // }
-
-  // const SymbolConjured* conjureSymbol(const Expr *expr,
-  //                                     const LocationContext *LCtx,
-  //                                     unsigned visitCount,
-  //                                     const void *symbolTag = nullptr) {
-  //   return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
-  // }
-
   /// Construct an SVal representing '0' for the specified type.
   DefinedOrUnknownSVal makeZeroVal(QualType type);
 
@@ -206,10 +191,6 @@ class SValBuilder {
   /// The advantage of symbols derived/built from other symbols is that we
   /// preserve the relation between related(or even equivalent) expressions, so
   /// conjured symbols should be used sparingly.
-  // DefinedOrUnknownSVal
-  // conjureSymbolVal(const void *symbolTag,
-  //                  const CFGBlock::ConstCFGElementRef elemRef,
-  //                  const LocationContext *LCtx, unsigned count);
   DefinedOrUnknownSVal
   conjureSymbolVal(const void *symbolTag,
                    const CFGBlock::ConstCFGElementRef elemRef,
@@ -219,25 +200,12 @@ class SValBuilder {
                    const LocationContext *LCtx, QualType type,
                    unsigned visitCount);
 
-  // /// Conjure a symbol representing heap allocated memory region.
-  // ///
-  // /// Note, the expression should represent a location.
-  // DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
-  //                                      const LocationContext *LCtx,
-  //                                      unsigned Count);
-
-  // /// Conjure a symbol representing heap allocated memory region.
-  // ///
-  // /// Note, now, the expression *doesn't* need to represent a location.
-  // /// But the type need to!
-  // DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
-  //                                      const LocationContext *LCtx,
-  //                                      QualType type, unsigned Count);
-
+  /// Conjure a symbol representing heap allocated memory region.
   DefinedSVal
   getConjuredHeapSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
                            const LocationContext *LCtx, QualType type,
                            unsigned Count);
+
   /// Create an SVal representing the result of an alloca()-like call, that is,
   /// an AllocaRegion on the stack.
   ///
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 05961f42c02c6..ebad2db530e55 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -103,15 +103,6 @@ class SymbolConjured : public SymbolData {
   }
 
 public:
-  /// It might return null.
-  // TODO: Remove
-  const Stmt *getStmt() const {
-    if (auto Stmt = ElemRef->getAs<CFGStmt>()) {
-      return Stmt->getStmt();
-    }
-    return nullptr;
-  }
-
   const CFGBlock::ConstCFGElementRef getCFGElementRef() const {
     return ElemRef;
   }
@@ -547,13 +538,6 @@ class SymbolManager {
   template <typename SymExprT, typename... Args>
   const SymExprT *acquire(Args &&...args);
 
-  // const SymbolConjured *conjureSymbol(const Stmt *E,
-  //                                     const LocationContext *LCtx, QualType
-  //                                     T, unsigned VisitCount, const void
-  //                                     *SymbolTag = nullptr) {
-  //   return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
-  // }
-
   const SymbolConjured *
   conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
                 const LocationContext *LCtx, QualType T, unsigned VisitCount,
@@ -562,13 +546,6 @@ class SymbolManager {
     return acquire<SymbolConjured>(ElemRef, LCtx, T, VisitCount, SymbolTag);
   }
 
-  // const SymbolConjured* conjureSymbol(const Expr *E,
-  //                                     const LocationContext *LCtx,
-  //                                     unsigned VisitCount,
-  //                                     const void *SymbolTag = nullptr) {
-  //   return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
-  // }
-
   QualType getType(const SymExpr *SE) const {
     return SE->getType();
   }
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index dd173a35cfd73..23440bdec31c9 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -205,30 +205,6 @@ SValBuilder::conjureSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
   return nonloc::SymbolVal(sym);
 }
 
-// DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
-//                                                   const LocationContext
-//                                                   *LCtx, unsigned VisitCount)
-//                                                   {
-//   QualType T = E->getType();
-//   return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
-// }
-//
-// DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
-//                                                   const LocationContext
-//                                                   *LCtx, QualType type,
-//                                                   unsigned VisitCount) {
-//   assert(Loc::isLocType(type));
-//   assert(SymbolManager::canSymbolicate(type));
-//   if (type->isNullPtrType()) {
-//     // makeZeroVal() returns UnknownVal only in case of FP number, which
-//     // is not the case.
-//     return makeZeroVal(type).castAs<DefinedSVal>();
-//   }
-//
-//   SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
-//   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
-// }
-
 DefinedSVal SValBuilder::getConjuredHeapSymbolVal(
     const CFGBlock::ConstCFGElementRef elemRef, const LocationContext *LCtx,
     QualType type, unsigned VisitCount) {
diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index d24b98161b4d8..5c2cfe164888a 100644
--- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -82,10 +82,8 @@ void UnarySymExpr::dumpToStream(raw_ostream &os) const {
 
 void SymbolConjured::dumpToStream(raw_ostream &os) const {
   os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
-  if (const auto *S = getStmt())
-    os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
-  else
-    os << ", no stmt";
+  os << ", CFGElemRef";
+  ElemRef->dumpToStream(os);
   os << ", #" << Count << '}';
 }
 

>From 52d69f174f43cccf3e2026ac6021c3018c3572b8 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sun, 23 Feb 2025 00:12:59 +0000
Subject: [PATCH 08/12] Implement getID for CFGElementRefImpl

---
 clang/include/clang/Analysis/CFG.h              | 6 ++++++
 clang/lib/StaticAnalyzer/Core/SymbolManager.cpp | 6 ++----
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index 3c0582d648f01..a665e313e4c15 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -700,6 +700,12 @@ class CFGBlock {
       ID.AddPointer(Parent);
       ID.AddInteger(Index);
     }
+
+    int64_t getID() const {
+      return Parent->getParent()
+          ->getAllocator()
+          .template identifyKnownAlignedObject<CFGElement>(&*this);
+    }
   };
 
   template <bool IsReverse, bool IsConst> class ElementRefIterator {
diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 5c2cfe164888a..41df94271c849 100644
--- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -81,10 +81,8 @@ void UnarySymExpr::dumpToStream(raw_ostream &os) const {
 }
 
 void SymbolConjured::dumpToStream(raw_ostream &os) const {
-  os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
-  os << ", CFGElemRef";
-  ElemRef->dumpToStream(os);
-  os << ", #" << Count << '}';
+  os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID()
+     << ", CFGElemRef" << ElemRef.getID() << ", #" << Count << '}';
 }
 
 void SymbolDerived::dumpToStream(raw_ostream &os) const {

>From b807790b432e0f89b14ab70a0f017394ffc3737e Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sun, 23 Feb 2025 00:13:14 +0000
Subject: [PATCH 09/12] Remove some more unused code

---
 clang/lib/StaticAnalyzer/Core/LoopWidening.cpp | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 617c8bf559a36..b34e13ece2631 100644
--- a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -25,22 +25,6 @@ using namespace clang::ast_matchers;
 
 const auto MatchRef = "matchref";
 
-/// Return the loops condition Stmt or NULL if LoopStmt is not a loop
-static const Expr *getLoopCondition(const Stmt *LoopStmt) {
-  switch (LoopStmt->getStmtClass()) {
-  default:
-    return nullptr;
-  case Stmt::ForStmtClass:
-    return cast<ForStmt>(LoopStmt)->getCond();
-  case Stmt::WhileStmtClass:
-    return cast<WhileStmt>(LoopStmt)->getCond();
-  case Stmt::DoStmtClass:
-    return cast<DoStmt>(LoopStmt)->getCond();
-  case Stmt::CXXForRangeStmtClass:
-    return cast<CXXForRangeStmt>(LoopStmt)->getCond();
-  }
-}
-
 namespace clang {
 namespace ento {
 

>From ef0e9ba5ed6706b998708eaf9d324e93e67c1280 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sun, 23 Feb 2025 00:55:31 +0000
Subject: [PATCH 10/12] Don't use CFGElementRef from CallEvent, fix some calls
 to conjureSymbolVal

---
 .../Core/PathSensitive/SValBuilder.h          |  4 ++
 .../Checkers/CStringChecker.cpp               | 41 +++++++++----------
 .../Checkers/ContainerModeling.cpp            | 34 ++++++++-------
 .../Checkers/ErrnoTesterChecker.cpp           |  6 +--
 .../Checkers/IteratorModeling.cpp             |  7 ++--
 .../StaticAnalyzer/Checkers/MallocChecker.cpp |  2 +-
 .../RetainCountChecker/RetainCountChecker.cpp |  2 +-
 .../Checkers/STLAlgorithmModeling.cpp         |  5 +--
 .../Checkers/SmartPtrModeling.cpp             |  4 +-
 .../Checkers/StdLibraryFunctionsChecker.cpp   |  4 +-
 .../StaticAnalyzer/Checkers/StreamChecker.cpp | 27 ++++++------
 .../Checkers/cert/InvalidPtrChecker.cpp       |  2 +-
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 16 ++++----
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp |  4 +-
 .../Core/ExprEngineCallAndReturn.cpp          |  2 +-
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 35 ++++++++--------
 16 files changed, 98 insertions(+), 97 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index c9fc8ae723258..004771bec087c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -192,6 +192,10 @@ class SValBuilder {
   /// preserve the relation between related(or even equivalent) expressions, so
   /// conjured symbols should be used sparingly.
   DefinedOrUnknownSVal
+  conjureSymbolVal(const void *symbolTag, const Expr *expr,
+                   const CFGBlock::ConstCFGElementRef elemRef,
+                   const LocationContext *LCtx, unsigned count);
+  DefinedOrUnknownSVal
   conjureSymbolVal(const void *symbolTag,
                    const CFGBlock::ConstCFGElementRef elemRef,
                    const LocationContext *LCtx, QualType type, unsigned count);
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index e54576be2ba04..5bd94e31c3df8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1515,8 +1515,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
       // conjure a return value for later.
       if (lastElement.isUnknown())
         lastElement = C.getSValBuilder().conjureSymbolVal(
-            nullptr, Call.getCFGElementRef(), LCtx,
-            Call.getOriginExpr()->getType(), C.blockCount());
+            nullptr, Call.getOriginExpr(), C.getCFGElementRef(), LCtx,
+            C.blockCount());
 
       // The byte after the last byte copied is the return value.
       state = state->BindExpr(Call.getOriginExpr(), LCtx, lastElement);
@@ -1666,9 +1666,9 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
     State = CheckBufferAccess(C, State, Left, Size, AccessKind::read, CK);
     if (State) {
       // The return value is the comparison result, which we don't know.
-      SVal CmpV = Builder.conjureSymbolVal(
-          nullptr, Call.getCFGElementRef(), LCtx,
-          Call.getOriginExpr()->getType(), C.blockCount());
+      SVal CmpV =
+          Builder.conjureSymbolVal(nullptr, Call.getOriginExpr(),
+                                   C.getCFGElementRef(), LCtx, C.blockCount());
       State = State->BindExpr(Call.getOriginExpr(), LCtx, CmpV);
       C.addTransition(State);
     }
@@ -1772,8 +1772,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
       // All we know is the return value is the min of the string length
       // and the limit. This is better than nothing.
       result = C.getSValBuilder().conjureSymbolVal(
-          nullptr, Call.getCFGElementRef(), LCtx,
-          Call.getOriginExpr()->getType(), C.blockCount());
+          nullptr, Call.getOriginExpr(), C.getCFGElementRef(), LCtx,
+          C.blockCount());
       NonLoc resultNL = result.castAs<NonLoc>();
 
       if (strLengthNL) {
@@ -1797,8 +1797,8 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
     // value, so it can be used in constraints, at least.
     if (result.isUnknown()) {
       result = C.getSValBuilder().conjureSymbolVal(
-          nullptr, Call.getCFGElementRef(), LCtx,
-          Call.getOriginExpr()->getType(), C.blockCount());
+          nullptr, C.getCFGElementRef(), LCtx, Call.getOriginExpr()->getType(),
+          C.blockCount());
     }
   }
 
@@ -2265,9 +2265,9 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
     // If this is a stpcpy-style copy, but we were unable to check for a buffer
     // overflow, we still need a result. Conjure a return value.
     if (ReturnEnd && Result.isUnknown()) {
-      Result = svalBuilder.conjureSymbolVal(
-          nullptr, Call.getCFGElementRef(), LCtx,
-          Call.getOriginExpr()->getType(), C.blockCount());
+      Result = svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(),
+                                            C.getCFGElementRef(), LCtx,
+                                            C.blockCount());
     }
   }
   // Set the return value.
@@ -2366,9 +2366,9 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
   const StringLiteral *RightStrLiteral =
       getCStringLiteral(C, state, Right.Expression, RightVal);
   bool canComputeResult = false;
-  SVal resultVal = svalBuilder.conjureSymbolVal(
-      nullptr, Call.getCFGElementRef(), LCtx, Call.getOriginExpr()->getType(),
-      C.blockCount());
+  SVal resultVal =
+      svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(),
+                                   C.getCFGElementRef(), LCtx, C.blockCount());
 
   if (LeftStrLiteral && RightStrLiteral) {
     StringRef LeftStrRef = LeftStrLiteral->getString();
@@ -2475,15 +2475,14 @@ void CStringChecker::evalStrsep(CheckerContext &C,
     // further along in the same string, or NULL if there are no more tokens.
     State =
         State->bindLoc(*SearchStrLoc,
-                       SVB.conjureSymbolVal(getTag(), Call.getCFGElementRef(),
+                       SVB.conjureSymbolVal(getTag(), C.getCFGElementRef(),
                                             LCtx, CharPtrTy, C.blockCount()),
                        LCtx);
   } else {
     assert(SearchStrVal.isUnknown());
     // Conjure a symbolic value. It's the best we can do.
-    Result =
-        SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
-                             Call.getOriginExpr()->getType(), C.blockCount());
+    Result = SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(),
+                                  C.getCFGElementRef(), LCtx, C.blockCount());
   }
 
   // Set the return value, and finish.
@@ -2527,8 +2526,8 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
   SValBuilder &SVB = C.getSValBuilder();
 
   SVal ResultVal =
-      SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
-                           Call.getOriginExpr()->getType(), C.blockCount());
+      SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), C.getCFGElementRef(),
+                           LCtx, C.blockCount());
   State = State->BindExpr(Call.getOriginExpr(), LCtx, ResultVal);
 
   C.addTransition(State);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 74a7b8e0f54ff..16579a691965b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/DeclTemplate.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -107,12 +108,13 @@ bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
 bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
 SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
 SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
-ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
-                                     const MemRegion *Cont, const Expr *E,
+ProgramStateRef createContainerBegin(ProgramStateRef State,
+                                     const MemRegion *Cont,
+                                     const CFGBlock::ConstCFGElementRef ElemRef,
                                      QualType T, const LocationContext *LCtx,
                                      unsigned BlockCount);
-ProgramStateRef createContainerEnd(CheckerContext &C, ProgramStateRef State,
-                                   const MemRegion *Cont, const Expr *E,
+ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
+                                   const CFGBlock::ConstCFGElementRef ElemRef,
                                    QualType T, const LocationContext *LCtx,
                                    unsigned BlockCount);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
@@ -260,9 +262,9 @@ void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
   auto State = C.getState();
   auto BeginSym = getContainerBegin(State, ContReg);
   if (!BeginSym) {
-    State =
-        createContainerBegin(C, State, ContReg, CE, C.getASTContext().LongTy,
-                             C.getLocationContext(), C.blockCount());
+    State = createContainerBegin(State, ContReg, C.getCFGElementRef(),
+                                 C.getASTContext().LongTy,
+                                 C.getLocationContext(), C.blockCount());
     BeginSym = getContainerBegin(State, ContReg);
   }
   State = setIteratorPosition(State, RetVal,
@@ -283,8 +285,9 @@ void ContainerModeling::handleEnd(CheckerContext &C, const Expr *CE,
   auto State = C.getState();
   auto EndSym = getContainerEnd(State, ContReg);
   if (!EndSym) {
-    State = createContainerEnd(C, State, ContReg, CE, C.getASTContext().LongTy,
-                               C.getLocationContext(), C.blockCount());
+    State = createContainerEnd(State, ContReg, C.getCFGElementRef(),
+                               C.getASTContext().LongTy, C.getLocationContext(),
+                               C.blockCount());
     EndSym = getContainerEnd(State, ContReg);
   }
   State = setIteratorPosition(State, RetVal,
@@ -845,8 +848,9 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
   return CDataPtr->getEnd();
 }
 
-ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
-                                     const MemRegion *Cont, const Expr *E,
+ProgramStateRef createContainerBegin(ProgramStateRef State,
+                                     const MemRegion *Cont,
+                                     const CFGBlock::ConstCFGElementRef ElemRef,
                                      QualType T, const LocationContext *LCtx,
                                      unsigned BlockCount) {
   // Only create if it does not exist
@@ -856,7 +860,7 @@ ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
 
   auto &SymMgr = State->getSymbolManager();
   const SymbolConjured *Sym =
-      SymMgr.conjureSymbol(C.getCFGElementRef(), LCtx, T, BlockCount, "begin");
+      SymMgr.conjureSymbol(ElemRef, LCtx, T, BlockCount, "begin");
   State = assumeNoOverflow(State, Sym, 4);
 
   if (CDataPtr) {
@@ -868,8 +872,8 @@ ProgramStateRef createContainerBegin(CheckerContext &C, ProgramStateRef State,
   return setContainerData(State, Cont, CData);
 }
 
-ProgramStateRef createContainerEnd(CheckerContext &C, ProgramStateRef State,
-                                   const MemRegion *Cont, const Expr *E,
+ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
+                                   const CFGBlock::ConstCFGElementRef ElemRef,
                                    QualType T, const LocationContext *LCtx,
                                    unsigned BlockCount) {
   // Only create if it does not exist
@@ -879,7 +883,7 @@ ProgramStateRef createContainerEnd(CheckerContext &C, ProgramStateRef State,
 
   auto &SymMgr = State->getSymbolManager();
   const SymbolConjured *Sym =
-      SymMgr.conjureSymbol(C.getCFGElementRef(), LCtx, T, BlockCount, "end");
+      SymMgr.conjureSymbol(ElemRef, LCtx, T, BlockCount, "end");
   State = assumeNoOverflow(State, Sym, 4);
 
   if (CDataPtr) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
index b47787d59fc62..65e3190d2dc22 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
@@ -130,9 +130,9 @@ void ErrnoTesterChecker::evalSetErrnoIfErrorRange(CheckerContext &C,
 
   ProgramStateRef StateFailure = State->BindExpr(
       Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
-  DefinedOrUnknownSVal ErrnoVal = SVB.conjureSymbolVal(
-      nullptr, Call.getCFGElementRef(), C.getLocationContext(),
-      Call.getOriginExpr()->getType(), C.blockCount());
+  DefinedOrUnknownSVal ErrnoVal =
+      SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), C.getCFGElementRef(),
+                           C.getLocationContext(), C.blockCount());
   StateFailure = StateFailure->assume(ErrnoVal, true);
   assert(StateFailure && "Failed to assume on an initial value.");
   StateFailure =
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 380991f10f499..12df1fb3d81d0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -356,15 +356,14 @@ IteratorModeling::handleOverloadedOperator(CheckerContext &C,
         return;
 
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleComparison(C, OrigExpr, Call.getCFGElementRef(),
+        handleComparison(C, OrigExpr, C.getCFGElementRef(),
                          Call.getReturnValue(), InstCall->getCXXThisVal(),
                          Call.getArgSVal(0), Op);
         return;
       }
 
-      handleComparison(C, OrigExpr, Call.getCFGElementRef(),
-                       Call.getReturnValue(), Call.getArgSVal(0),
-                       Call.getArgSVal(1), Op);
+      handleComparison(C, OrigExpr, C.getCFGElementRef(), Call.getReturnValue(),
+                       Call.getArgSVal(0), Call.getArgSVal(1), Op);
       return;
     } else if (isRandomIncrOrDecrOperator(Op)) {
       const auto *OrigExpr = Call.getOriginExpr();
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 825bb977d7e60..857974be0c582 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1835,7 +1835,7 @@ ProgramStateRef MallocChecker::MallocBindRetVal(CheckerContext &C,
   const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
   DefinedSVal RetVal =
       isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
-               : SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
+               : SVB.getConjuredHeapSymbolVal(C.getCFGElementRef(), LCtx,
                                               CE->getType(), Count);
   return State->BindExpr(CE, C.getLocationContext(), RetVal);
 }
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index 939a8544e28b7..e2f98bace3f59 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -931,7 +931,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
     if (RetVal.isUnknown() ||
         (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
       SValBuilder &SVB = C.getSValBuilder();
-      RetVal = SVB.conjureSymbolVal(nullptr, Call.getCFGElementRef(), LCtx,
+      RetVal = SVB.conjureSymbolVal(nullptr, C.getCFGElementRef(), LCtx,
                                     ResultTy, C.blockCount());
     }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
index f19ef750cae8c..ce424dbfa9b85 100644
--- a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
@@ -132,8 +132,8 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
   auto &SVB = C.getSValBuilder();
   const auto *LCtx = C.getLocationContext();
 
-  SVal RetVal = SVB.conjureSymbolVal(nullptr, C.getCFGElementRef(), LCtx,
-                                     CE->getType(), C.blockCount());
+  SVal RetVal = SVB.conjureSymbolVal(nullptr, CE, C.getCFGElementRef(), LCtx,
+                                     C.blockCount());
   SVal Param = State->getSVal(CE->getArg(paramNum), LCtx);
 
   auto StateFound = State->BindExpr(CE, LCtx, RetVal);
@@ -202,4 +202,3 @@ void ento::registerSTLAlgorithmModeling(CheckerManager &Mgr) {
 bool ento::shouldRegisterSTLAlgorithmModeling(const CheckerManager &mgr) {
   return true;
 }
-
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index 7ccb9210e4c58..fa4cf3e2ceeba 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -306,7 +306,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
       return false;
 
     const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
-        Call.getCFGElementRef(), C.getLocationContext(),
+        C.getCFGElementRef(), C.getLocationContext(),
         getPointerTypeFromTemplateArg(Call, C), C.blockCount());
 
     const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
@@ -853,7 +853,7 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
 
     const LocationContext *LC = C.getLocationContext();
     InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
-        Call.getCFGElementRef(), LC, InnerPointerType, C.blockCount());
+        C.getCFGElementRef(), LC, InnerPointerType, C.blockCount());
     State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
   }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 354797a3325d6..633877ada4742 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -585,7 +585,7 @@ class StdLibraryFunctionsChecker
                           CheckerContext &C) const override {
       SValBuilder &SVB = C.getSValBuilder();
       NonLoc ErrnoSVal =
-          SVB.conjureSymbolVal(&Tag, Call.getCFGElementRef(),
+          SVB.conjureSymbolVal(&Tag, C.getCFGElementRef(),
                                C.getLocationContext(), C.getASTContext().IntTy,
                                C.blockCount())
               .castAs<NonLoc>();
@@ -1479,7 +1479,7 @@ bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
     const LocationContext *LC = C.getLocationContext();
     const auto *CE = cast<CallExpr>(Call.getOriginExpr());
     SVal V = C.getSValBuilder().conjureSymbolVal(
-        Call.getCFGElementRef(), LC, CE->getType().getCanonicalType(),
+        C.getCFGElementRef(), LC, CE->getType().getCanonicalType(),
         C.blockCount());
     State = State->BindExpr(CE, LC, V);
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 49e332eb2a44a..2a890b96fa0e1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -13,6 +13,7 @@
 #include "NoOwnershipChangeVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
@@ -229,8 +230,7 @@ DefinedSVal makeRetVal(CheckerContext &C, const CallExpr *CE) {
 
   const LocationContext *LCtx = C.getLocationContext();
   return C.getSValBuilder()
-      .conjureSymbolVal(nullptr, C.getCFGElementRef(), LCtx, CE->getType(),
-                        C.blockCount())
+      .conjureSymbolVal(nullptr, CE, C.getCFGElementRef(), LCtx, C.blockCount())
       .castAs<DefinedSVal>();
 }
 
@@ -833,11 +833,10 @@ static std::optional<int64_t> getKnownValue(ProgramStateRef State, SVal V) {
 /// Invalidate only the requested elements instead of the whole buffer.
 /// This is basically a refinement of the more generic 'escapeArgs' or
 /// the plain old 'invalidateRegions'.
-static ProgramStateRef
-escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
-                           unsigned BlockCount, const SubRegion *Buffer,
-                           QualType ElemType, int64_t StartIndex,
-                           int64_t ElementCount) {
+static ProgramStateRef escapeByStartIndexAndCount(
+    ProgramStateRef State, const CallEvent &Call, unsigned BlockCount,
+    const SubRegion *Buffer, QualType ElemType, int64_t StartIndex,
+    int64_t ElementCount, const CFGBlock::ConstCFGElementRef ElemRef) {
   constexpr auto DoNotInvalidateSuperRegion =
       RegionAndSymbolInvalidationTraits::InvalidationKinds::
           TK_DoNotInvalidateSuperRegion;
@@ -858,10 +857,10 @@ escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
     EscapingVals.push_back(loc::MemRegionVal(Element));
     ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
   }
-  return State->invalidateRegions(
-      EscapingVals, Call.getCFGElementRef(), BlockCount, LCtx,
-      /*CausesPointerEscape=*/false,
-      /*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
+  return State->invalidateRegions(EscapingVals, ElemRef, BlockCount, LCtx,
+                                  /*CausesPointerEscape=*/false,
+                                  /*InvalidatedSymbols=*/nullptr, &Call,
+                                  &ITraits);
 }
 
 static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
@@ -1139,9 +1138,9 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
 
     constexpr int MaxInvalidatedElementsLimit = 64;
     if (NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) {
-      return escapeByStartIndexAndCount(State, Call, C.blockCount(), Buffer,
-                                        ElemTy, *StartIndexVal,
-                                        NumCompleteOrIncompleteElementsRead);
+      return escapeByStartIndexAndCount(
+          State, Call, C.blockCount(), Buffer, ElemTy, *StartIndexVal,
+          NumCompleteOrIncompleteElementsRead, C.getCFGElementRef());
     }
   }
   return nullptr;
diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
index 044f9ba61113b..3c8ddacfd78a4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
@@ -207,7 +207,7 @@ void InvalidPtrChecker::postPreviousReturnInvalidatingCall(
 
   // Function call will return a pointer to the new symbolic region.
   DefinedOrUnknownSVal RetVal = C.getSValBuilder().conjureSymbolVal(
-      Call.getCFGElementRef(), LCtx, CE->getType(), C.blockCount());
+      C.getCFGElementRef(), LCtx, CE->getType(), C.blockCount());
   State = State->BindExpr(CE, LCtx, RetVal);
 
   const auto *SymRegOfRetVal =
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 169983605f5f0..18fdc30b86c94 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -22,7 +22,7 @@ using namespace ento;
 using llvm::APSInt;
 
 /// Optionally conjure and return a symbol for offset when processing
-/// an expression \p Expression.
+/// a \p CFGElementRef.
 /// 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.
@@ -32,7 +32,6 @@ static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
                                           QualType Ty, SValBuilder &svalBuilder,
                                           unsigned Count,
                                           const LocationContext *LCtx) {
-  // QualType Ty = Expression->getType();
   if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
       Symbol.isUnknown()) {
     return svalBuilder.conjureSymbolVal(elemRef, LCtx, Ty, Count);
@@ -68,8 +67,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
       // FIXME: Handle structs.
       if (RightV.isUnknown()) {
         unsigned Count = currBldrCtx->blockCount();
-        RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
-                                              B->getRHS()->getType(), Count);
+        RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(),
+                                              getCFGElementRef(), LCtx, Count);
       }
       // Simulate the effects of a "store":  bind the value of the RHS
       // to the L-Value represented by the LHS.
@@ -844,8 +843,8 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
   }
 
   if (!hasValue)
-    V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
-                                     Ex->getType(), currBldrCtx->blockCount());
+    V = svalBuilder.conjureSymbolVal(nullptr, Ex, getCFGElementRef(), LCtx,
+                                     currBldrCtx->blockCount());
 
   // Generate a new node with the binding from the appropriate path.
   B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
@@ -1126,9 +1125,8 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
 
     // Conjure a new symbol if necessary to recover precision.
     if (Result.isUnknown()){
-      DefinedOrUnknownSVal SymVal =
-          svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
-                                       U->getType(), currBldrCtx->blockCount());
+      DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal(
+          nullptr, U, getCFGElementRef(), LCtx, currBldrCtx->blockCount());
       Result = SymVal;
 
       // If the value is a location, ++/-- should always preserve
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 0860402778826..90fbaafe1c1ee 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -970,8 +970,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
       symVal = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,
                                                     CNE->getType(), blockCount);
     else
-      symVal = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
-                                            CNE->getType(), blockCount);
+      symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, getCFGElementRef(),
+                                            LCtx, blockCount);
   }
 
   CallEventManager &CEMgr = getStateManager().getCallEventManager();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 9bbfb3710f315..4634c63a5059c 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -800,7 +800,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
     // a regular unknown pointer.
     const auto *CNE = dyn_cast<CXXNewExpr>(E);
     if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
-      R = svalBuilder.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
+      R = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,
                                                E->getType(), Count);
       const MemRegion *MR = R.getAsRegion()->StripCasts();
 
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 23440bdec31c9..2f4b281cc2b5e 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -151,24 +151,23 @@ SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
   return nonloc::SymbolVal(sym);
 }
 
-// DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
-//                                                    const Expr *Ex,
-//                                                    const LocationContext
-//                                                    *LCtx, unsigned Count) {
-//   QualType T = Ex->getType();
-//
-//   if (T->isNullPtrType())
-//     return makeZeroVal(T);
-//
-//   // Compute the type of the result. If the expression is not an R-value, the
-//   // result should be a location.
-//   QualType ExType = Ex->getType();
-//   if (Ex->isGLValue())
-//     T =
-//     LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
-//
-//   return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
-// }
+DefinedOrUnknownSVal
+SValBuilder::conjureSymbolVal(const void *SymbolTag, const Expr *Ex,
+                              const CFGBlock::ConstCFGElementRef elemRef,
+                              const LocationContext *LCtx, unsigned Count) {
+  QualType T = Ex->getType();
+
+  if (T->isNullPtrType())
+    return makeZeroVal(T);
+
+  // Compute the type of the result. If the expression is not an R-value, the
+  // result should be a location.
+  QualType ExType = Ex->getType();
+  if (Ex->isGLValue())
+    T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
+
+  return conjureSymbolVal(SymbolTag, elemRef, LCtx, T, Count);
+}
 
 DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(
     const void *symbolTag, const CFGBlock::ConstCFGElementRef elemRef,

>From b17999edc00cd97ff67c746af562c44d497cff89 Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sun, 23 Feb 2025 01:08:03 +0000
Subject: [PATCH 11/12] Fix another call to conjureSymbolVal

---
 clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 5bd94e31c3df8..41a13e2e8efcb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1797,7 +1797,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
     // value, so it can be used in constraints, at least.
     if (result.isUnknown()) {
       result = C.getSValBuilder().conjureSymbolVal(
-          nullptr, C.getCFGElementRef(), LCtx, Call.getOriginExpr()->getType(),
+          nullptr, Call.getOriginExpr(), C.getCFGElementRef(), LCtx,
           C.blockCount());
     }
   }

>From 1d46adede0ec2cbc05e651818a658ddfdd4da61f Mon Sep 17 00:00:00 2001
From: Fangyi Zhou <me at fangyi.io>
Date: Sun, 23 Feb 2025 01:15:01 +0000
Subject: [PATCH 12/12] Remove a redundant parameter in handleComparison

---
 .../Checkers/IteratorModeling.cpp             | 25 ++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 12df1fb3d81d0..f2161e8698f13 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -99,8 +99,7 @@ class IteratorModeling
                                  const Expr *OrigExpr,
                                  const AdvanceFn *Handler) const;
 
-  void handleComparison(CheckerContext &C, const Expr *CE,
-                        const CFGBlock::ConstCFGElementRef ElemRef, SVal RetVal,
+  void handleComparison(CheckerContext &C, const Expr *CE, SVal RetVal,
                         SVal LVal, SVal RVal, OverloadedOperatorKind Op) const;
   void processComparison(CheckerContext &C, ProgramStateRef State,
                          SymbolRef Sym1, SymbolRef Sym2, SVal RetVal,
@@ -272,7 +271,7 @@ void IteratorModeling::checkPostStmt(const BinaryOperator *BO,
 
   if (isSimpleComparisonOperator(BO->getOpcode())) {
     SVal Result = State->getSVal(BO, C.getLocationContext());
-    handleComparison(C, BO, C.getCFGElementRef(), Result, LVal, RVal,
+    handleComparison(C, BO, Result, LVal, RVal,
                      BinaryOperator::getOverloadedOperator(OK));
   } else if (isRandomIncrOrDecrOperator(OK)) {
     // In case of operator+ the iterator can be either on the LHS (eg.: it + 1),
@@ -356,14 +355,13 @@ IteratorModeling::handleOverloadedOperator(CheckerContext &C,
         return;
 
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleComparison(C, OrigExpr, C.getCFGElementRef(),
-                         Call.getReturnValue(), InstCall->getCXXThisVal(),
-                         Call.getArgSVal(0), Op);
+        handleComparison(C, OrigExpr, Call.getReturnValue(),
+                         InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
         return;
       }
 
-      handleComparison(C, OrigExpr, C.getCFGElementRef(), Call.getReturnValue(),
-                       Call.getArgSVal(0), Call.getArgSVal(1), Op);
+      handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
+                       Call.getArgSVal(1), Op);
       return;
     } else if (isRandomIncrOrDecrOperator(Op)) {
       const auto *OrigExpr = Call.getOriginExpr();
@@ -445,10 +443,9 @@ IteratorModeling::handleAdvanceLikeFunction(CheckerContext &C,
   }
 }
 
-void IteratorModeling::handleComparison(
-    CheckerContext &C, const Expr *CE,
-    const CFGBlock::ConstCFGElementRef ElemRef, SVal RetVal, SVal LVal,
-    SVal RVal, OverloadedOperatorKind Op) const {
+void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
+                                        SVal RetVal, SVal LVal, SVal RVal,
+                                        OverloadedOperatorKind Op) const {
   // Record the operands and the operator of the comparison for the next
   // evalAssume, if the result is a symbolic expression. If it is a concrete
   // value (only one branch is possible), then transfer the state between
@@ -470,7 +467,7 @@ void IteratorModeling::handleComparison(
   SymbolRef Sym;
   if (!LPos || !RPos) {
     auto &SymMgr = C.getSymbolManager();
-    Sym = SymMgr.conjureSymbol(ElemRef, C.getLocationContext(),
+    Sym = SymMgr.conjureSymbol(C.getCFGElementRef(), C.getLocationContext(),
                                C.getASTContext().LongTy, C.blockCount());
     State = assumeNoOverflow(State, Sym, 4);
   }
@@ -497,7 +494,7 @@ void IteratorModeling::handleComparison(
     auto &SymMgr = C.getSymbolManager();
     auto *LCtx = C.getLocationContext();
     RetVal = nonloc::SymbolVal(SymMgr.conjureSymbol(
-        ElemRef, LCtx, C.getASTContext().BoolTy, C.blockCount()));
+        C.getCFGElementRef(), LCtx, C.getASTContext().BoolTy, C.blockCount()));
     State = State->BindExpr(CE, LCtx, RetVal);
   }
 



More information about the cfe-commits mailing list