[clang] f40c234 - [NFC][analyzer] Spread use of 'Expr*' instead of 'Stmt*' (#188319)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 7 04:47:22 PDT 2026
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;
More information about the cfe-commits
mailing list