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

Fangyi Zhou via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 21 15:51:42 PST 2025


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

Closes #57270.

This PR changes the `Stmt *` field in `SymbolConjured` with `CFGBlock::ConstCFGElementRef`. The motivation is that, when conjuring a symbol, there might not always be a statement available, causing information to be lost for conjured symbols, whereas the CFGElementRef can always be provided at the callsite.

Following the idea, this PR changes callsites of functions to create conjured symbols, and replaces them with appropriate `CFGElementRef`s.

>From 97c4e0e39ba5e9486e893691b40e78fe3d8548b0 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 1/3] 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 c3dcdc985a935..0a1c71ecf34a0 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);
@@ -2054,9 +2054,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 de88ff7db8000ef61e1076c57d56211c5185dea3 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 2/3] 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 d01b6ae55f611..3034907c041ee 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 1fc679c931ec910f380359d318532fb5274f093e 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 3/3] 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 4166cf14391e2..dd03dfb100af5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1832,8 +1832,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 7e74b418b3353..e6541e378e0a9 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";



More information about the cfe-commits mailing list