Skip to content

Commit b343f3f

Browse files
authored
[analyzer][NFC] Cleanup BranchNodeBuilder (#117898)
Previously `BranchNodeBuilder` had a machinery to mark the two possible branches (true, false) as infeasible, but this was completely useless in practice, because the `BranchNodeBuilder` objects where short-lived local variables so the `markInfeasible()` calls did not affect any later calls. The only theoretical exception was that in `ExprEngine::processBranch` the methods of `BranchNodeBuilder` were called within a `for` loop that iterates over the nodes created by the `check::BranchCondition` callbacks. However, currently only two checkers listen to `check::BranchCondition` and neither of them produces multiple out nodes. This is fortunate, because if the `for` loop had multiple iterations, then the lingering effects of `markInfeasible()` would have caused wildly incorrect behavior. _For example, let's assume that a hypothetical `check::BranchCondition` callback transitions to two different states, and the condition expression happens to be true in the first and false in the second. In this situation the first iteration of the loop would mark the false branch as 'infeasible' and then in the second iteration the analyzer would skip creating the transition to the false branch (from the state where that is the 'right' path forward)._ After removing `markInfeasible()`, it became clear that the `isFeasible()` calls in `ExprEngine::processBranch` are redundant because they only guarded a `generateNode` call -- which immediately calls `isFeasible()` and does nothing on an infeasible branch. At this point in the refactoring the only code writing the feasibility data members is their initialization in the constructors of `BranchNodeBuilder` and the only code reading them is the check at the beginning of `BranchNodeBuilder::generateNode`, so it was straightforward to remove them completely and simplify the logic of `generateNode()` to let it directly check the nullness of the `CFGBlock*` pointer that it wants to use. Finally, after these changes it became clear that in `ExprEngine::processBranch` the `else` branch (corresponding to the case when `assumeCondition` fails) is equivalent to the "normal" case, so I eliminated it as well. I also update the capitalization of a few variables that are already affected by this change.
1 parent b27d97b commit b343f3f

File tree

3 files changed

+21
-59
lines changed

3 files changed

+21
-59
lines changed

clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -429,47 +429,27 @@ class BranchNodeBuilder: public NodeBuilder {
429429
const CFGBlock *DstT;
430430
const CFGBlock *DstF;
431431

432-
bool InFeasibleTrue;
433-
bool InFeasibleFalse;
434-
435432
void anchor() override;
436433

437434
public:
438435
BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
439-
const NodeBuilderContext &C,
440-
const CFGBlock *dstT, const CFGBlock *dstF)
441-
: NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
442-
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
436+
const NodeBuilderContext &C, const CFGBlock *DT,
437+
const CFGBlock *DF)
438+
: NodeBuilder(SrcNode, DstSet, C), DstT(DT), DstF(DF) {
443439
// The branch node builder does not generate autotransitions.
444440
// If there are no successors it means that both branches are infeasible.
445441
takeNodes(SrcNode);
446442
}
447443

448444
BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
449-
const NodeBuilderContext &C,
450-
const CFGBlock *dstT, const CFGBlock *dstF)
451-
: NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
452-
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
445+
const NodeBuilderContext &C, const CFGBlock *DT,
446+
const CFGBlock *DF)
447+
: NodeBuilder(SrcSet, DstSet, C), DstT(DT), DstF(DF) {
453448
takeNodes(SrcSet);
454449
}
455450

456451
ExplodedNode *generateNode(ProgramStateRef State, bool branch,
457452
ExplodedNode *Pred);
458-
459-
const CFGBlock *getTargetBlock(bool branch) const {
460-
return branch ? DstT : DstF;
461-
}
462-
463-
void markInfeasible(bool branch) {
464-
if (branch)
465-
InFeasibleTrue = true;
466-
else
467-
InFeasibleFalse = true;
468-
}
469-
470-
bool isFeasible(bool branch) {
471-
return branch ? !InFeasibleTrue : !InFeasibleFalse;
472-
}
473453
};
474454

475455
class IndirectGotoNodeBuilder {

clang/lib/StaticAnalyzer/Core/CoreEngine.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,15 @@ StmtNodeBuilder::~StmtNodeBuilder() {
649649
void BranchNodeBuilder::anchor() {}
650650

651651
ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
652-
bool branch,
652+
bool Branch,
653653
ExplodedNode *NodePred) {
654-
// If the branch has been marked infeasible we should not generate a node.
655-
if (!isFeasible(branch))
654+
const CFGBlock *Dst = Branch ? DstT : DstF;
655+
656+
if (!Dst)
656657
return nullptr;
657658

658-
ProgramPoint Loc = BlockEdge(C.getBlock(), branch ? DstT : DstF,
659-
NodePred->getLocationContext());
659+
ProgramPoint Loc =
660+
BlockEdge(C.getBlock(), Dst, NodePred->getLocationContext());
660661
ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
661662
return Succ;
662663
}

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,10 +1647,8 @@ void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
16471647
ProgramStateRef State = Pred->getState();
16481648
const LocationContext *LC = Pred->getLocationContext();
16491649
if (getObjectUnderConstruction(State, BTE, LC)) {
1650-
TempDtorBuilder.markInfeasible(false);
16511650
TempDtorBuilder.generateNode(State, true, Pred);
16521651
} else {
1653-
TempDtorBuilder.markInfeasible(true);
16541652
TempDtorBuilder.generateNode(State, false, Pred);
16551653
}
16561654
}
@@ -2770,7 +2768,6 @@ void ExprEngine::processBranch(const Stmt *Condition,
27702768
// Check for NULL conditions; e.g. "for(;;)"
27712769
if (!Condition) {
27722770
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
2773-
NullCondBldr.markInfeasible(false);
27742771
NullCondBldr.generateNode(Pred->getState(), true, Pred);
27752772
return;
27762773
}
@@ -2790,40 +2787,25 @@ void ExprEngine::processBranch(const Stmt *Condition,
27902787
if (CheckersOutSet.empty())
27912788
return;
27922789

2793-
BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2790+
BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
27942791
for (ExplodedNode *PredN : CheckersOutSet) {
27952792
if (PredN->isSink())
27962793
continue;
27972794

27982795
ProgramStateRef PrevState = PredN->getState();
27992796

2800-
ProgramStateRef StTrue, StFalse;
2797+
ProgramStateRef StTrue = PrevState, StFalse = PrevState;
28012798
if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))
28022799
std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2803-
else {
2804-
assert(!isa<ObjCForCollectionStmt>(Condition));
2805-
builder.generateNode(PrevState, true, PredN);
2806-
builder.generateNode(PrevState, false, PredN);
2807-
continue;
2808-
}
2800+
28092801
if (StTrue && StFalse)
28102802
assert(!isa<ObjCForCollectionStmt>(Condition));
28112803

2812-
// Process the true branch.
2813-
if (builder.isFeasible(true)) {
2814-
if (StTrue)
2815-
builder.generateNode(StTrue, true, PredN);
2816-
else
2817-
builder.markInfeasible(true);
2818-
}
2804+
if (StTrue)
2805+
Builder.generateNode(StTrue, true, PredN);
28192806

2820-
// Process the false branch.
2821-
if (builder.isFeasible(false)) {
2822-
if (StFalse)
2823-
builder.generateNode(StFalse, false, PredN);
2824-
else
2825-
builder.markInfeasible(false);
2826-
}
2807+
if (StFalse)
2808+
Builder.generateNode(StFalse, false, PredN);
28272809
}
28282810
currBldrCtx = nullptr;
28292811
}
@@ -2845,14 +2827,13 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
28452827
const auto *VD = cast<VarDecl>(DS->getSingleDecl());
28462828
ProgramStateRef state = Pred->getState();
28472829
bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2848-
BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
2830+
BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
28492831

28502832
if (!initHasRun) {
28512833
state = state->add<InitializedGlobalsSet>(VD);
28522834
}
28532835

2854-
builder.generateNode(state, initHasRun, Pred);
2855-
builder.markInfeasible(!initHasRun);
2836+
Builder.generateNode(state, initHasRun, Pred);
28562837

28572838
currBldrCtx = nullptr;
28582839
}

0 commit comments

Comments
 (0)