https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/181431
From fdc6c6022a0944d7ceeb3a36eef23fb99d147e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Fri, 13 Feb 2026 23:17:36 +0100 Subject: [PATCH 1/2] [NFC][analyzer] Remove StmtNodeBuilder The class `StmtNodeBuilder` was practically equivalent to its base class `NodeBuilder` -- its data members and constructors were identical and the only distinguishing feature was that it supported two additional methods that were not present in `NodeBuilder`. This commit moves those two methods to `NodeBuilder` (there is no reason why they cannot be defined there) and replaces all references to `StmtNodeBuilder` with plain `NodeBuilder`. Note that previously `StmtNodeBuilder` had a distinguishing feature where its destructor could pass nodes to an "enclosing node builder" but this became dead code somewhen in the past, so my previous commit 320d0b5467b9586a188e06dd2620126f5cb99318 removed it. --- .../Core/PathSensitive/CoreEngine.h | 51 ++++++------------- .../Core/PathSensitive/ExprEngine.h | 5 +- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 42 +++++++-------- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 35 ++++++------- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 32 ++++++------ .../Core/ExprEngineCallAndReturn.cpp | 2 +- .../StaticAnalyzer/Core/ExprEngineObjC.cpp | 22 ++++---- clang/test/Analysis/misc-ps-eager-assume.m | 3 ++ 8 files changed, 89 insertions(+), 103 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index f8d444251ec9f..5ff9a1025a5e3 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -291,39 +291,6 @@ class NodeBuilder { return generateNodeImpl(PP, State, Pred, true); } - const ExplodedNodeSet &getResults() { return Frontier; } - - const NodeBuilderContext &getContext() { return C; } - bool hasGeneratedNodes() { return HasGeneratedNodes; } - - void takeNodes(const ExplodedNodeSet &S) { - for (const auto I : S) - Frontier.erase(I); - } - - void takeNodes(ExplodedNode *N) { Frontier.erase(N); } - void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); } - void addNodes(ExplodedNode *N) { Frontier.Add(N); } -}; - -/// \class StmtNodeBuilder -/// This builder class is useful for generating nodes that resulted from -/// visiting a statement. The main difference from its parent NodeBuilder is -/// that it creates a statement specific ProgramPoint. -/// FIXME: This class is not meaningfully different from plain NodeBuilder. -class StmtNodeBuilder : public NodeBuilder { -public: - StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, - const NodeBuilderContext &Ctx) - : NodeBuilder(SrcNode, DstSet, Ctx) {} - - StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, - const NodeBuilderContext &Ctx) - : NodeBuilder(SrcSet, DstSet, Ctx) {} - - using NodeBuilder::generateNode; - using NodeBuilder::generateSink; - ExplodedNode *generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, @@ -331,7 +298,7 @@ class StmtNodeBuilder : public NodeBuilder { ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); - return NodeBuilder::generateNode(L, St, Pred); + return generateNode(L, St, Pred); } ExplodedNode *generateSink(const Stmt *S, @@ -341,8 +308,22 @@ class StmtNodeBuilder : public NodeBuilder { ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); - return NodeBuilder::generateSink(L, St, Pred); + return generateSink(L, St, Pred); } + + const ExplodedNodeSet &getResults() { return Frontier; } + + const NodeBuilderContext &getContext() { return C; } + bool hasGeneratedNodes() { return HasGeneratedNodes; } + + void takeNodes(const ExplodedNodeSet &S) { + for (const auto I : S) + Frontier.erase(I); + } + + void takeNodes(ExplodedNode *N) { Frontier.erase(N); } + void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); } + void addNodes(ExplodedNode *N) { Frontier.Add(N); } }; /// BranchNodeBuilder is responsible for constructing the nodes diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 20f62f93f9095..40bc96c954267 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -616,11 +616,10 @@ class ExprEngine { ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex, const LocationContext *LCtx, QualType T, QualType ExTy, const CastExpr *CastE, - StmtNodeBuilder &Bldr, - ExplodedNode *Pred); + NodeBuilder &Bldr, ExplodedNode *Pred); void handleUOExtension(ExplodedNode *N, const UnaryOperator *U, - StmtNodeBuilder &Bldr); + NodeBuilder &Bldr); public: SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 47312a53f61ff..e0bc083f6b978 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1088,7 +1088,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, // For each node in CheckedSet, generate CleanedNodes that have the // environment, the store, and the constraints cleaned up but have the // user-supplied states as the predecessors. - StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx); + NodeBuilder Bldr(CheckedSet, Out, *currBldrCtx); for (const auto I : CheckedSet) { ProgramStateRef CheckerState = I->getState(); @@ -1599,8 +1599,8 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, } ExplodedNodeSet CleanDtorState; - StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx); - StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State); + NodeBuilder Builder(Pred, CleanDtorState, *currBldrCtx); + Builder.generateNode(D.getBindTemporaryExpr(), Pred, State); QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType(); // FIXME: Currently CleanDtorState can be empty here due to temporaries being @@ -1672,7 +1672,7 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, Dst = PreVisit; return; } - StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx); + NodeBuilder Builder(PreVisit, Dst, *currBldrCtx); for (ExplodedNode *Node : PreVisit) { ProgramStateRef State = Node->getState(); const LocationContext *LC = Node->getLocationContext(); @@ -1683,7 +1683,7 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, // temporary destructor nodes. State = addObjectUnderConstruction(State, BTE, LC, UnknownVal()); } - StmtBldr.generateNode(BTE, Node, State); + Builder.generateNode(BTE, Node, State); } } @@ -1719,7 +1719,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), S->getBeginLoc(), "Error evaluating statement"); ExplodedNodeSet Dst; - StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx); + NodeBuilder Bldr(Pred, DstTop, *currBldrCtx); assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens()); @@ -2002,7 +2002,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this); ExplodedNodeSet Tmp; - StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx); + NodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx); const Expr *ArgE; if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S)) @@ -2049,7 +2049,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this); ExplodedNodeSet Tmp; - StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx); + NodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx); const auto *Ex = cast<Expr>(S); QualType resultType = Ex->getType(); @@ -3179,7 +3179,7 @@ void ExprEngine::processSwitch(NodeBuilderContext &BC, const SwitchStmt *Switch, void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); @@ -3344,7 +3344,7 @@ void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, Ex, *this); ExplodedNodeSet EvalSet; - StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); const Expr *Arr = Ex->getCommonExpr()->getSourceExpr(); @@ -3445,7 +3445,7 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A, getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this); ExplodedNodeSet EvalSet; - StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); bool IsVectorType = A->getBase()->getType()->isVectorType(); @@ -3501,7 +3501,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, for (const auto I : CheckedSet) VisitCommonDeclRefExpr(M, Member, I, EvalSet); } else { - StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); ExplodedNodeSet Tmp; for (const auto I : CheckedSet) { @@ -3583,7 +3583,7 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred, // FIXME: Ideally we should model the behavior of the atomics precisely here. ExplodedNodeSet AfterInvalidateSet; - StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx); + NodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx); for (const auto I : AfterPreSet) { ProgramStateRef State = I->getState(); @@ -3725,7 +3725,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val, StoreE, AtDeclInit, *this, *PP); - StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx); + NodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx); // If the location is not a 'Loc', it will already be handled by // the checkers. There is nothing left to do. @@ -3808,7 +3808,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, if (Tmp.empty()) return; - StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx); + NodeBuilder Bldr(Tmp, Dst, *currBldrCtx); if (location.isUndef()) return; @@ -3836,7 +3836,7 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, ProgramStateRef state, SVal location, bool isLoad) { - StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx); + NodeBuilder BldrTop(Pred, Dst, *currBldrCtx); // Early checks for performance reason. if (location.isUnknown()) { return; @@ -3844,7 +3844,7 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, ExplodedNodeSet Src; BldrTop.takeNodes(Pred); - StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx); + NodeBuilder Bldr(Pred, Src, *currBldrCtx); if (Pred->getState() != state) { // Associate this new state with an ExplodedNode. // FIXME: If I pass null tag, the graph is incorrect, e.g for @@ -3881,7 +3881,7 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(LastEagerlyAssumeExprIfSuccessful, void ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex) { - StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx); + NodeBuilder Bldr(Src, Dst, *currBldrCtx); for (ExplodedNode *Pred : Src) { // Test if the previous node was as the same expression. This can happen @@ -3930,7 +3930,7 @@ bool ExprEngine::didEagerlyAssumeBifurcateAt(ProgramStateRef State, void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); // We have processed both the inputs and the outputs. All of the outputs // should evaluate to Locs. Nuke all of their values. @@ -3967,7 +3967,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); Bldr.generateNode(A, Pred, Pred->getState()); } @@ -4134,7 +4134,7 @@ void ExprEngine::ConstructInitList(const Expr *E, ArrayRef<Expr *> Args, const LocationContext *LC = Pred->getLocationContext(); - StmtNodeBuilder B(Pred, Dst, *currBldrCtx); + NodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef S = Pred->getState(); QualType T = E->getType().getCanonicalType(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index db27c06cd18a3..b7fac30500d26 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -78,7 +78,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, } if (!B->isAssignmentOp()) { - StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); + NodeBuilder Bldr(*it, Tmp2, *currBldrCtx); if (B->isAdditiveOp()) { // TODO: This can be removed after we enable history tracking with @@ -246,7 +246,7 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, } ExplodedNodeSet Tmp; - StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); + NodeBuilder Bldr(Pred, Tmp, *currBldrCtx); Bldr.generateNode(BE, Pred, State->BindExpr(BE, Pred->getLocationContext(), V), nullptr, ProgramPoint::PostLValueKind); @@ -255,10 +255,11 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); } -ProgramStateRef ExprEngine::handleLValueBitCast( - ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, - QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, - ExplodedNode* Pred) { +ProgramStateRef +ExprEngine::handleLValueBitCast(ProgramStateRef state, const Expr *Ex, + const LocationContext *LCtx, QualType T, + QualType ExTy, const CastExpr *CastE, + NodeBuilder &Bldr, ExplodedNode *Pred) { if (T->isLValueReferenceType()) { assert(!CastE->getType()->isLValueReferenceType()); ExTy = getContext().getLValueReferenceType(ExTy); @@ -310,7 +311,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, } // Simulate the operation that actually casts the original value to a new // value of the destination type : - StmtNodeBuilder Bldr(DstEvalLoc, Dst, *currBldrCtx); + NodeBuilder Bldr(DstEvalLoc, Dst, *currBldrCtx); for (ExplodedNode *Node : DstEvalLoc) { ProgramStateRef State = Node->getState(); @@ -338,7 +339,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) T = ExCast->getTypeAsWritten(); - StmtNodeBuilder Bldr(DstPreStmt, Dst, *currBldrCtx); + NodeBuilder Bldr(DstPreStmt, Dst, *currBldrCtx); for (ExplodedNode *Pred : DstPreStmt) { ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); @@ -579,7 +580,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder B(Pred, Dst, *currBldrCtx); + NodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef State = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); @@ -629,7 +630,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); ExplodedNodeSet dstEvaluated; - StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); + NodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); I!=E; ++I) { ExplodedNode *N = *I; @@ -698,7 +699,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, assert(B->getOpcode() == BO_LAnd || B->getOpcode() == BO_LOr); - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); if (B->getType()->isVectorType()) { @@ -779,7 +780,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, ExplodedNodeSet &Dst) { assert(L && R); - StmtNodeBuilder B(Pred, Dst, *currBldrCtx); + NodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); const CFGBlock *SrcBlock = nullptr; @@ -839,7 +840,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, void ExprEngine:: VisitOffsetOfExpr(const OffsetOfExpr *OOE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder B(Pred, Dst, *currBldrCtx); + NodeBuilder B(Pred, Dst, *currBldrCtx); Expr::EvalResult Result; if (OOE->EvaluateAsInt(Result, getContext())) { APSInt IV = Result.Val.getInt(); @@ -864,7 +865,7 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); ExplodedNodeSet EvalSet; - StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); @@ -899,7 +900,7 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, } void ExprEngine::handleUOExtension(ExplodedNode *N, const UnaryOperator *U, - StmtNodeBuilder &Bldr) { + NodeBuilder &Bldr) { // FIXME: We can probably just have some magic in Environment::getSVal() // that propagates values, instead of creating a new node here. // @@ -920,7 +921,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); ExplodedNodeSet EvalSet; - StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); for (ExplodedNode *N : CheckedSet) { switch (U->getOpcode()) { @@ -1065,7 +1066,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, evalLoad(Tmp, U, Ex, Pred, state, loc); ExplodedNodeSet Dst2; - StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); + NodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); for (ExplodedNode *N : Tmp) { state = N->getState(); assert(LCtx == N->getLocationContext()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 99751482dee40..43dad6fef7d65 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -33,7 +33,7 @@ using namespace ento; void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); const Expr *tempExpr = ME->getSubExpr()->IgnoreParens(); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); @@ -563,7 +563,7 @@ void ExprEngine::handleConstructor(const Expr *E, // it in fact constructs into the correct target. This constructor can // therefore be skipped. Target = *ElidedTarget; - StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); + NodeBuilder Bldr(Pred, destNodes, *currBldrCtx); State = finishObjectConstruction(State, CE, LCtx); if (auto L = Target.getAs<Loc>()) State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); @@ -604,7 +604,7 @@ void ExprEngine::handleConstructor(const Expr *E, // No element construction will happen in a 0 size array. if (isZeroSizeArray()) { - StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); + NodeBuilder Bldr(Pred, destNodes, *currBldrCtx); static SimpleProgramPointTag T{"ExprEngine", "Skipping 0 size array construction"}; Bldr.generateNode(CE, Pred, State, &T); @@ -688,7 +688,7 @@ void ExprEngine::handleConstructor(const Expr *E, static SimpleProgramPointTag T("ExprEngine", "Prepare for object construction"); ExplodedNodeSet DstPrepare; - StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx); + NodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx); Pred = BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind); if (!Pred) @@ -709,7 +709,7 @@ void ExprEngine::handleConstructor(const Expr *E, ExplodedNodeSet PreInitialized; if (CE) { // FIXME: Is it possible and/or useful to do this before PreStmt? - StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); + NodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); for (ExplodedNode *N : DstPreVisit) { ProgramStateRef State = N->getState(); if (CE->requiresZeroInitialization()) { @@ -748,7 +748,7 @@ void ExprEngine::handleConstructor(const Expr *E, if (CE && CE->getConstructor()->isTrivial() && CE->getConstructor()->isCopyOrMoveConstructor() && !CallOpts.IsArrayCtorOrDtor) { - StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); + NodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); // FIXME: Handle other kinds of trivial constructors as well. for (ExplodedNode *N : DstPreCall) performTrivialCopy(Bldr, N, *Call); @@ -767,7 +767,7 @@ void ExprEngine::handleConstructor(const Expr *E, // later (for life-time extended temporaries) -- but avoids infeasible // paths when no-return temporary destructors are used for assertions. ExplodedNodeSet DstEvaluatedPostProcessed; - StmtNodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx); + NodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx); const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext(); if (!ADC->getCFGBuildOptions().AddTemporaryDtors) { if (llvm::isa_and_nonnull<CXXTempObjectRegion, @@ -881,7 +881,7 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType, *Call, *this); ExplodedNodeSet DstInvalidated; - StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); + NodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); for (ExplodedNode *N : DstPreCall) defaultEvalCall(Bldr, N, *Call, CallOpts); @@ -906,7 +906,7 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, *Call, *this); ExplodedNodeSet DstPostCall; - StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx); + NodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx); for (ExplodedNode *I : DstPreCall) { // Operator new calls (CXXNewExpr) are intentionally not eval-called, // because it does not make sense to eval-call user-provided functions. @@ -923,7 +923,7 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, // Store return value of operator new() for future use, until the actual // CXXNewExpr gets processed. ExplodedNodeSet DstPostValue; - StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx); + NodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx); for (ExplodedNode *I : DstPostCall) { // FIXME: Because CNE serves as the "call site" for the allocator (due to // lack of a better expression in the AST), the conjured return value symbol @@ -1029,7 +1029,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, State = State->assume(*dSymVal, true); } - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); SVal Result = symVal; @@ -1114,7 +1114,7 @@ void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNodeSet DstPostCall; if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { - StmtNodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx); + NodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx); for (ExplodedNode *I : DstPreCall) { // Intentionally either inline or conservative eval-call the operator // delete, but avoid triggering an eval-call event for checkers. @@ -1142,13 +1142,13 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ProgramStateRef state = Pred->getState(); state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); Bldr.generateNode(CS, Pred, state); } void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); // Get the this object region from StoreManager. const LocationContext *LCtx = Pred->getLocationContext(); @@ -1226,7 +1226,7 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, SVal LambdaRVal = State->getSVal(R); ExplodedNodeSet Tmp; - StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); + NodeBuilder Bldr(Pred, Tmp, *currBldrCtx); // FIXME: is this the right program point kind? Bldr.generateNode(LE, Pred, State->BindExpr(LE, LocCtxt, LambdaRVal), @@ -1242,7 +1242,7 @@ void ExprEngine::VisitAttributedStmt(const AttributedStmt *A, getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this); ExplodedNodeSet EvalSet; - StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); + NodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx); for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(A->getAttrs())) { for (ExplodedNode *N : CheckerPreStmt) { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index ac6c1d76b6b8e..a407a923d7d0f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -1311,7 +1311,7 @@ void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, ExplodedNodeSet dstPreVisit; getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this); - StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx); + NodeBuilder B(dstPreVisit, Dst, *currBldrCtx); if (RS->getRetValue()) { for (ExplodedNodeSet::iterator it = dstPreVisit.begin(), diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index f2e5a163afb62..bb0fd6ded2def 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -27,7 +27,7 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, SVal location = state->getLValue(Ex->getDecl(), baseVal); ExplodedNodeSet dstIvar; - StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx); + NodeBuilder Bldr(Pred, dstIvar, *currBldrCtx); Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); // Perform the post-condition check of the ObjCIvarRefExpr and store @@ -43,11 +43,13 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, /// Generate a node in \p Bldr for an iteration statement using ObjC /// for-loop iterator. -static void populateObjCForDestinationSet( - ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder, - const ObjCForCollectionStmt *S, ConstCFGElementRef elem, SVal elementV, - SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx, - StmtNodeBuilder &Bldr, bool hasElements) { +static void populateObjCForDestinationSet(ExplodedNodeSet &dstLocation, + SValBuilder &svalBuilder, + const ObjCForCollectionStmt *S, + ConstCFGElementRef elem, + SVal elementV, SymbolManager &SymMgr, + const NodeBuilderContext *currBldrCtx, + NodeBuilder &Bldr, bool hasElements) { for (ExplodedNode *Pred : dstLocation) { ProgramStateRef state = Pred->getState(); @@ -130,7 +132,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, for (ExplodedNode *dstLocation : DstLocation) { ExplodedNodeSet DstLocationSingleton{dstLocation}, Tmp; - StmtNodeBuilder Bldr(dstLocation, Tmp, *currBldrCtx); + NodeBuilder Bldr(dstLocation, Tmp, *currBldrCtx); if (!isContainerNull) populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, @@ -211,7 +213,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, // Receiver is definitely nil, so run ObjCMessageNil callbacks and return. if (nilState && !notNilState) { ExplodedNodeSet dstNil; - StmtNodeBuilder Bldr(Pred, dstNil, *currBldrCtx); + NodeBuilder Bldr(Pred, dstNil, *currBldrCtx); bool HasTag = Pred->getLocation().getTag(); Pred = Bldr.generateNode(ME, Pred, nilState, nullptr, ProgramPoint::PreStmtKind); @@ -229,7 +231,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, } ExplodedNodeSet dstNonNil; - StmtNodeBuilder Bldr(Pred, dstNonNil, *currBldrCtx); + NodeBuilder Bldr(Pred, dstNonNil, *currBldrCtx); // Generate a transition to the non-nil state, dropping any potential // nil flow. if (notNilState != State) { @@ -253,7 +255,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, // Proceed with evaluate the message expression. ExplodedNodeSet dstEval; - StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx); + NodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx); for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(), DE = dstGenericPrevisit.end(); DI != DE; ++DI) { diff --git a/clang/test/Analysis/misc-ps-eager-assume.m b/clang/test/Analysis/misc-ps-eager-assume.m index 37395616ee928..f6ae458090715 100644 --- a/clang/test/Analysis/misc-ps-eager-assume.m +++ b/clang/test/Analysis/misc-ps-eager-assume.m @@ -132,6 +132,9 @@ void rdar7342806(void) { // Note: CheckerVisit mistakenly cleared an existing node, and the cleared // node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where // 'p' was not assigned. +// Note 2: This "resurrecting" destructor was removed from the codebase by +// commit 320d0b5467b9586a188e06dd2620126f5cb99318 (in 2026) because it was +// already dead code at that time. //===---------------------------------------------------------------------===// float *pr5627_f(int y); From 7f46fe9a5a30e7142a0b36a7d04c7eb2e85b84ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Tue, 17 Feb 2026 13:12:33 +0100 Subject: [PATCH 2/2] Mark some methods as const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 5ff9a1025a5e3..a7fe34b425d5d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -311,10 +311,10 @@ class NodeBuilder { return generateSink(L, St, Pred); } - const ExplodedNodeSet &getResults() { return Frontier; } + const ExplodedNodeSet &getResults() const { return Frontier; } - const NodeBuilderContext &getContext() { return C; } - bool hasGeneratedNodes() { return HasGeneratedNodes; } + const NodeBuilderContext &getContext() const { return C; } + bool hasGeneratedNodes() const { return HasGeneratedNodes; } void takeNodes(const ExplodedNodeSet &S) { for (const auto I : S) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
