Author: DonĂ¡t Nagy
Date: 2026-04-07T13:47:17+02:00
New Revision: f40c234191802154d5b3fc3209908c3f2d6e1649

URL: 
https://github.com/llvm/llvm-project/commit/f40c234191802154d5b3fc3209908c3f2d6e1649
DIFF: 
https://github.com/llvm/llvm-project/commit/f40c234191802154d5b3fc3209908c3f2d6e1649.diff

LOG: [NFC][analyzer] Spread use of 'Expr*' instead of 'Stmt*' (#188319)

When I was browsing the codebase, I was surprised to see that the first
parameter of `ProgramStateRef::BindExpr` was `const Stmt*` instead of
`const Expr*`. As I surveyed calls to `BindExpr`, I realized that
fortunately no code passes non-expression statements to `BindExpr`
(anymore... it seems that earlier we had such hacks) so in this commit
I'm able to change the type of the first parameter to `const Expr*`.

There was a call to `BindExpr` where the first argument was the value of
the data member `StackFrameContext::CallSite`, so I also changed the
type of that member from `const Stmt*` to `const Expr*` because it was
another statement pointer that always pointed to expressions (or null).

This commit prepares the ground for using `Expr*` instead of `Stmt*` in
`EnvironmentEntry`, which is currently a `pair<const Stmt *, const
StackFrameContext *>` and will be updated in follow-up commits.

This commit also includes minor unrelated simplifications and
corrections.

Added: 
    

Modified: 
    clang/include/clang/Analysis/AnalysisDeclContext.h
    clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
    clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
    clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    clang/lib/Analysis/AnalysisDeclContext.cpp
    
clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
    clang/lib/StaticAnalyzer/Core/BugReporter.cpp
    clang/lib/StaticAnalyzer/Core/CallEvent.cpp
    clang/lib/StaticAnalyzer/Core/Environment.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    clang/lib/StaticAnalyzer/Core/MemRegion.cpp
    clang/lib/StaticAnalyzer/Core/ProgramState.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/AnalysisDeclContext.h 
b/clang/include/clang/Analysis/AnalysisDeclContext.h
index 2368b8ed911e7..00785d6d1db51 100644
--- a/clang/include/clang/Analysis/AnalysisDeclContext.h
+++ b/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -179,7 +179,7 @@ class AnalysisDeclContext {
 
   /// \copydoc LocationContextManager::getStackFrame()
   const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
-                                         const Stmt *S, const CFGBlock *Blk,
+                                         const Expr *E, const CFGBlock *Blk,
                                          unsigned BlockCount, unsigned Index);
 
   /// \copydoc LocationContextManager::getBlockInvocationContext()
@@ -300,7 +300,7 @@ class StackFrameContext : public LocationContext {
   friend class LocationContextManager;
 
   // The call site where this stack frame is established.
-  const Stmt *CallSite;
+  const Expr *CallSite;
 
   // The parent block of the call site.
   const CFGBlock *Block;
@@ -314,15 +314,15 @@ class StackFrameContext : public LocationContext {
   const unsigned Index;
 
   StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
-                    const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
+                    const Expr *E, const CFGBlock *Block, unsigned BlockCount,
                     unsigned Index, int64_t ID)
-      : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
+      : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(E),
         Block(Block), BlockCount(BlockCount), Index(Index) {}
 
 public:
   ~StackFrameContext() override = default;
 
-  const Stmt *getCallSite() const { return CallSite; }
+  const Expr *getCallSite() const { return CallSite; }
 
   const CFGBlock *getCallSiteBlock() const { return Block; }
 
@@ -335,10 +335,10 @@ class StackFrameContext : public LocationContext {
   void Profile(llvm::FoldingSetNodeID &ID) override;
 
   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
-                      const LocationContext *ParentLC, const Stmt *S,
+                      const LocationContext *ParentLC, const Expr *E,
                       const CFGBlock *Block, unsigned BlockCount,
                       unsigned Index) {
-    ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
+    ProfileCommon(ID, StackFrame, ADC, ParentLC, E);
     ID.AddPointer(Block);
     ID.AddInteger(BlockCount);
     ID.AddInteger(Index);
@@ -397,15 +397,16 @@ class LocationContextManager {
   ///
   /// \param ADC        The AnalysisDeclContext.
   /// \param ParentLC   The parent context of this newly created context.
-  /// \param S          The call.
+  /// \param E          The call expression.
   /// \param Block      The basic block.
-  /// \param BlockCount The current count of entering into \p Blk.
-  /// \param Index      The index of \p Blk.
-  /// \returns The context for \p D with parent context \p ParentLC.
+  /// \param BlockCount The current count of entering into \p Block.
+  /// \param StmtIdx    The index of the call expression \p E among the
+  ///                   statements of the CFGBlock \p Block.
+  /// \returns The stack frame context corresponding to the call.
   const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
                                          const LocationContext *ParentLC,
-                                         const Stmt *S, const CFGBlock *Block,
-                                         unsigned BlockCount, unsigned Index);
+                                         const Expr *E, const CFGBlock *Block,
+                                         unsigned BlockCount, unsigned 
StmtIdx);
 
   /// Obtain a context of the block invocation using its parent context.
   ///
@@ -472,14 +473,6 @@ class AnalysisDeclContextManager {
                                    0);
   }
 
-  /// \copydoc LocationContextManager::getStackFrame()
-  const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
-                                         const LocationContext *Parent,
-                                         const Stmt *S, const CFGBlock *Block,
-                                         unsigned BlockCount, unsigned Index) {
-    return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
-  }
-
   BodyFarm &getBodyFarm();
 
   /// Discard all previously created AnalysisDeclContexts.

diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 66da79970ca19..0b9202bcf274e 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -259,7 +259,7 @@ class CallEvent {
   virtual RuntimeDefinition getRuntimeDefinition() const = 0;
 
   /// Returns the expression whose value will be the result of this call.
-  /// May be null.
+  /// Null if and only if 'this' is a CXXDestructorCall.
   virtual const Expr *getOriginExpr() const {
     return Origin.dyn_cast<const Expr *>();
   }

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index 498e36e1431fa..56453df79819e 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -32,6 +32,11 @@ class SymbolReaper;
 /// This allows the environment to manage context-sensitive bindings,
 /// which is essentially for modeling recursive function analysis, among
 /// other things.
+/// FIXME: Use 'Expr' instead of 'Stmt' because associating a result with a
+/// non-expression statement does not make sense. Currently the environment
+/// only containts 'Expr's; and there is only one easy-to-eliminate hack in
+/// 'processCallExit' and 'Environment::getSVal' that constructs and handles
+/// 'EnvironmentEntry' instances with a 'ReturnStmt' as the 'first' part.
 class EnvironmentEntry : public std::pair<const Stmt *,
                                           const StackFrameContext *> {
 public:
@@ -52,7 +57,7 @@ class EnvironmentEntry : public std::pair<const Stmt *,
   }
 };
 
-/// An immutable map from EnvironemntEntries to SVals.
+/// An immutable map from EnvironmentEntries to SVals.
 class Environment {
 private:
   friend class EnvironmentManager;

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index d3dd6ca124b7f..942f5544c2b2e 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -278,9 +278,9 @@ class ProgramState : public llvm::FoldingSetNode {
   // Binding and retrieving values to/from the environment and symbolic store.
   //==---------------------------------------------------------------------==//
 
-  /// Create a new state by binding the value 'V' to the statement 'S' in the
-  /// state's environment.
-  [[nodiscard]] ProgramStateRef BindExpr(const Stmt *S,
+  /// Create a new state by binding the value \p V to the expression \p E in
+  /// the state's environment.
+  [[nodiscard]] ProgramStateRef BindExpr(const Expr *E,
                                          const LocationContext *LCtx, SVal V,
                                          bool Invalidate = true) const;
 

diff  --git a/clang/lib/Analysis/AnalysisDeclContext.cpp 
b/clang/lib/Analysis/AnalysisDeclContext.cpp
index 6f153e7e65255..266d20632e3cc 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -312,9 +312,9 @@ BodyFarm &AnalysisDeclContextManager::getBodyFarm() { 
return FunctionBodyFarm; }
 
 const StackFrameContext *
 AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
-                                   const Stmt *S, const CFGBlock *Blk,
+                                   const Expr *E, const CFGBlock *Blk,
                                    unsigned BlockCount, unsigned Index) {
-  return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
+  return getLocationContextManager().getStackFrame(this, ParentLC, E, Blk,
                                                    BlockCount, Index);
 }
 
@@ -428,15 +428,16 @@ void 
BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
 
//===----------------------------------------------------------------------===//
 
 const StackFrameContext *LocationContextManager::getStackFrame(
-    AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
-    const CFGBlock *blk, unsigned blockCount, unsigned idx) {
+    AnalysisDeclContext *Ctx, const LocationContext *Parent, const Expr *E,
+    const CFGBlock *Blk, unsigned BlockCount, unsigned StmtIdx) {
   llvm::FoldingSetNodeID ID;
-  StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
+  StackFrameContext::Profile(ID, Ctx, Parent, E, Blk, BlockCount, StmtIdx);
   void *InsertPos;
   auto *L =
    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, 
InsertPos));
   if (!L) {
-    L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
+    L = new StackFrameContext(Ctx, Parent, E, Blk, BlockCount, StmtIdx,
+                              ++NewID);
     Contexts.InsertNode(L, InsertPos);
   }
   return L;
@@ -514,9 +515,9 @@ void LocationContext::dumpStack(raw_ostream &Out) const {
         Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
       else
         Out << "Calling anonymous code";
-      if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
+      if (const Expr *E = cast<StackFrameContext>(LCtx)->getCallSite()) {
         Out << " at line ";
-        printLocation(Out, SM, S->getBeginLoc());
+        printLocation(Out, SM, E->getBeginLoc());
       }
       break;
     case Block:
@@ -556,8 +557,8 @@ void LocationContext::printJson(raw_ostream &Out, const 
char *NL,
         Out << "anonymous code";
 
       Out << "\", \"location\": ";
-      if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
-        printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
+      if (const Expr *E = cast<StackFrameContext>(LCtx)->getCallSite()) {
+        printSourceLocationAsJson(Out, E->getBeginLoc(), SM);
       } else {
         Out << "null";
       }

diff  --git 
a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
 
b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
index 98b0fbeb72fbb..6d4389fda8753 100644
--- 
a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
+++ 
b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
@@ -172,7 +172,7 @@ void UninitializedObjectChecker::checkEndFunction(
     return;
 
   PathDiagnosticLocation LocUsedForUniqueing;
-  const Stmt *CallSite = Context.getStackFrame()->getCallSite();
+  const Expr *CallSite = Context.getStackFrame()->getCallSite();
   if (CallSite)
     LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
         CallSite, Context.getSourceManager(), Node->getLocationContext());

diff  --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 4c066520b668f..51039da20afba 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -323,7 +323,7 @@ std::string StackHintGeneratorForSymbol::getMessage(const 
ExplodedNode *N){
   CallExitEnd CExit = P.castAs<CallExitEnd>();
 
   // FIXME: Use CallEvent to abstract this over all calls.
-  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
+  const Expr *CallSite = CExit.getCalleeContext()->getCallSite();
   const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
   if (!CE)
     return {};

diff  --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index e23f9fff4533a..eb32b9e581291 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -186,7 +186,7 @@ CallEvent::getCalleeStackFrame(unsigned BlockCount) const {
         break;
   assert(Idx < Sz);
 
-  return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx);
+  return ADC->getStackFrame(LCtx, E, B, BlockCount, Idx);
 }
 
 const ParamVarRegion
@@ -1480,7 +1480,7 @@ CallEventManager::getCaller(const StackFrameContext 
*CalleeCtx,
                                           CalleeCtx->getIndex()};
   assert(CallerCtx && "This should not be used for top-level stack frames");
 
-  const Stmt *CallSite = CalleeCtx->getCallSite();
+  const Expr *CallSite = CalleeCtx->getCallSite();
 
   if (CallSite) {
     if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx, ElemRef))
@@ -1494,13 +1494,11 @@ CallEventManager::getCaller(const StackFrameContext 
*CalleeCtx,
     if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite))
       return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerCtx,
                                    ElemRef);
-    else if (const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(CallSite))
+    if (const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(CallSite))
       return getCXXInheritedConstructorCall(CIE, ThisVal.getAsRegion(), State,
                                             CallerCtx, ElemRef);
-    else {
-      // All other cases are handled by getCall.
-      llvm_unreachable("This is not an inlineable statement");
-    }
+    // All other cases are handled by getCall.
+    llvm_unreachable("This is not an inlineable statement");
   }
 
   // Fall back to the CFG. The only thing we haven't handled yet is

diff  --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp 
b/clang/lib/StaticAnalyzer/Core/Environment.cpp
index 5d9cbf681a5e9..bfe973afc3210 100644
--- a/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -121,6 +121,11 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
     return *svalBuilder.getConstantVal(cast<Expr>(S));
 
   case Stmt::ReturnStmtClass: {
+    // FIXME: Move this logic to ExprEngine::processCallExit (the only location
+    // passes a ReturnStmt to this method) and then there will be no need to
+    // accept non-expression statements in getSVal (in fact, it will be
+    // possible to change the first member of EnvironmentEntry from const Stmt*
+    // to const Expr*).
     const auto *RS = cast<ReturnStmt>(S);
     if (const Expr *RE = RS->getRetValue())
       return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 4b24ac61337da..995a43c7e7aaf 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1885,7 +1885,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       // GNU __null is a pointer-width integer, not an actual pointer.
       ProgramStateRef state = Pred->getState();
       state = state->BindExpr(
-          S, Pred->getLocationContext(),
+          cast<Expr>(S), Pred->getLocationContext(),
           svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
       Bldr.generateNode(S, Pred, state);
       break;
@@ -2017,7 +2017,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       const LocationContext *LCtx = Pred->getLocationContext();
       for (const auto I : PreVisit) {
         ProgramStateRef State = I->getState();
-        State = State->BindExpr(S, LCtx, *ConstantVal);
+        State = State->BindExpr(cast<Expr>(S), LCtx, *ConstantVal);
         if (IsTemporary)
           State = createTemporaryRegionIfNeeded(State, LCtx,
                                                 cast<Expr>(S),
@@ -2443,13 +2443,15 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
       const auto *PE = cast<PseudoObjectExpr>(S);
       if (const Expr *Result = PE->getResultExpr()) {
         SVal V = state->getSVal(Result, Pred->getLocationContext());
-        Bldr.generateNode(S, Pred,
-                          state->BindExpr(S, Pred->getLocationContext(), V));
+        Bldr.generateNode(
+            S, Pred,
+            state->BindExpr(cast<Expr>(S), Pred->getLocationContext(), V));
       }
       else
         Bldr.generateNode(S, Pred,
-                          state->BindExpr(S, Pred->getLocationContext(),
-                                                   UnknownVal()));
+                          state->BindExpr(cast<Expr>(S),
+                                          Pred->getLocationContext(),
+                                          UnknownVal()));
 
       Bldr.addNodes(Dst);
       break;
@@ -2464,8 +2466,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
       const Expr *E = OIE->getSubExpr();
       SVal V = state->getSVal(E, Pred->getLocationContext());
-      Bldr.generateNode(S, Pred,
-              state->BindExpr(S, Pred->getLocationContext(), V));
+      Bldr.generateNode(
+          S, Pred,
+          state->BindExpr(cast<Expr>(S), Pred->getLocationContext(), V));
       Bldr.addNodes(Dst);
       break;
     }
@@ -2478,7 +2481,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
   const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();
   assert(CalleeSF && CallerSF);
   ExplodedNode *BeforeProcessingCall = nullptr;
-  const Stmt *CE = CalleeSF->getCallSite();
+  const Expr *CE = CalleeSF->getCallSite();
 
   // Find the first node before we started processing the call expression.
   while (N) {
@@ -2515,9 +2518,16 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
       BeforeProcessingCall->getLocationContext(), CE, nullptr, &PT);
   // Add the special flag to GDM to signal retrying with no inlining.
   // Note, changing the state ensures that we are not going to cache out.
+  // NOTE: This stores the call site (CE) in the state trait, but the the
+  // actual pointer value is only checked by an assertion; for the analysis,
+  // only the presence or absence of this trait matters.
+  // TODO: If we are handling a destructor call, CE is nullpointer (because it
+  // ultimately comes from the `Origin` of a `CXXDestructorCall`), which is
+  // indistinguishable from the absence (default state) of this state trait.
+  // I don't think that this bad logic causes actually observable problems, but
+  // it would be nice to clean it up if somebody has time to do so.
   ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
-  NewNodeState =
-    NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
+  NewNodeState = NewNodeState->set<ReplayWithoutInlining>(CE);
 
   // Make the new node a successor of BeforeProcessingCall.
   bool IsNew = false;

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 701c7fdc88497..5807b4db61fef 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -231,7 +231,7 @@ SVal ExprEngine::computeObjectUnderConstruction(
 
         unsigned NVCaller = getNumVisited(CallerLCtx, SFC->getCallSiteBlock());
         return computeObjectUnderConstruction(
-            cast<Expr>(SFC->getCallSite()), State, NVCaller, CallerLCtx,
+            SFC->getCallSite(), State, NVCaller, CallerLCtx,
             RTC->getConstructionContext(), CallOpts);
       } else {
         // We are on the top frame of the analysis. We do not know where is the
@@ -454,8 +454,8 @@ ProgramStateRef ExprEngine::updateObjectsUnderConstruction(
         assert(!isa<BlockInvocationContext>(CallerLCtx));
       }
 
-      return updateObjectsUnderConstruction(V,
-          cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
+      return updateObjectsUnderConstruction(
+          V, SFC->getCallSite(), State, CallerLCtx,
           RTC->getConstructionContext(), CallOpts);
     }
     case ConstructionContext::ElidedTemporaryObjectKind: {

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index b4dc4fa8a077d..3dc3c9d05f24e 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -259,7 +259,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
   // look up the first enclosing stack frame.
   const StackFrameContext *CallerCtx = CalleeCtx->getParent()->getStackFrame();
 
-  const Stmt *CE = CalleeCtx->getCallSite();
+  const Expr *CE = CalleeCtx->getCallSite();
   ProgramStateRef State = CEBNode->getState();
   // Find the last statement in the function and the corresponding basic block.
   auto [LastSt, Blk] = getLastStmt(CEBNode);
@@ -297,6 +297,10 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
   if (CE) {
     if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
       const LocationContext *LCtx = CEBNode->getLocationContext();
+      // FIXME: This tries to look up the return statement in the environment,
+      // which is special cased to look up the subexpression RS->getRetValue()
+      // in environment. Instead of relying on this hack, pass
+      // RS->getRetValue() to getSVal() after checking it for nullness.
       SVal V = State->getSVal(RS, LCtx);
 
       // Ensure that the return type matches the type of the returned Expr.
@@ -304,10 +308,8 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
         QualType ReturnedTy =
             CallEvent::getDeclaredResultType(CalleeCtx->getDecl());
         if (!ReturnedTy.isNull()) {
-          if (const Expr *Ex = dyn_cast<Expr>(CE)) {
-            V = adjustReturnValue(V, Ex->getType(), ReturnedTy,
-                                  getStoreManager());
-          }
+          V = adjustReturnValue(V, CE->getType(), ReturnedTy,
+                                getStoreManager());
         }
       }
 
@@ -587,7 +589,7 @@ void ExprEngine::inlineCall(WorkList *WList, const 
CallEvent &Call,
 }
 
 static ProgramStateRef getInlineFailedState(ProgramStateRef State,
-                                            const Stmt *CallE) {
+                                            const Expr *CallE) {
   const void *ReplayState = State->get<ReplayWithoutInlining>();
   if (!ReplayState)
     return nullptr;
@@ -1225,9 +1227,6 @@ void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, 
ExplodedNode *Pred,
     return;
   }
 
-  // Try to inline the call.
-  // The origin expression here is just used as a kind of checksum;
-  // this should still be safe even for CallEvents that don't come from exprs.
   const Expr *E = Call.getOriginExpr();
 
   ProgramStateRef InlinedFailedState = getInlineFailedState(State, E);

diff  --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index f20e79ae675a4..5544d254929e5 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1044,21 +1044,26 @@ const VarRegion *MemRegionManager::getVarRegion(const 
VarDecl *D,
   if (PVD) {
     unsigned Index = PVD->getFunctionScopeIndex();
     const StackFrameContext *SFC = LC->getStackFrame();
-    const Stmt *CallSite = SFC->getCallSite();
+    const Expr *CallSite = SFC->getCallSite();
     if (CallSite) {
-      const Decl *D = SFC->getDecl();
-      if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
-        if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
-          return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
-                                              getStackArgumentsRegion(SFC));
-      } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
-        if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
-          return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
-                                              getStackArgumentsRegion(SFC));
-      } else {
-        return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
+      const Decl *CalleeDecl = SFC->getDecl();
+      bool ValidParam = true;
+      if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
+        ValidParam =
+            (Index < FD->param_size() && FD->getParamDecl(Index) == PVD);
+      } else if (const auto *BD = dyn_cast<BlockDecl>(CalleeDecl)) {
+        ValidParam =
+            (Index < BD->param_size() && BD->getParamDecl(Index) == PVD);
+      }
+
+      if (ValidParam) {
+        return getSubRegion<ParamVarRegion>(CallSite, Index,
                                             getStackArgumentsRegion(SFC));
       }
+      // FIXME: If ValidParam was false, this method would "fall through" and
+      // eventually return a NonParamVarRegion for this ParamVarDecl. That
+      // seems to be buggy, so I strongly suspect that ValidParam always ends
+      // up being true.
     }
   }
 

diff  --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp 
b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 87485daa6e5c9..297719af34209 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -298,12 +298,11 @@ SVal ProgramState::getSVal(Loc location, QualType T) 
const {
   return V;
 }
 
-ProgramStateRef ProgramState::BindExpr(const Stmt *S,
-                                           const LocationContext *LCtx,
-                                           SVal V, bool Invalidate) const{
-  Environment NewEnv =
-    getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
-                                      Invalidate);
+ProgramStateRef ProgramState::BindExpr(const Expr *E,
+                                       const LocationContext *LCtx, SVal V,
+                                       bool Invalidate) const {
+  Environment NewEnv = getStateManager().EnvMgr.bindExpr(
+      Env, EnvironmentEntry(E, LCtx), V, Invalidate);
   if (NewEnv == Env)
     return this;
 


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

Reply via email to