Skip to content

Commit 4d2ef60

Browse files
committed
[analyzer][NFC] Cleanup BranchNodeBuilder
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.
1 parent 7b2a708 commit 4d2ef60

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
@@ -1655,10 +1655,8 @@ void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
16551655
ProgramStateRef State = Pred->getState();
16561656
const LocationContext *LC = Pred->getLocationContext();
16571657
if (getObjectUnderConstruction(State, BTE, LC)) {
1658-
TempDtorBuilder.markInfeasible(false);
16591658
TempDtorBuilder.generateNode(State, true, Pred);
16601659
} else {
1661-
TempDtorBuilder.markInfeasible(true);
16621660
TempDtorBuilder.generateNode(State, false, Pred);
16631661
}
16641662
}
@@ -2778,7 +2776,6 @@ void ExprEngine::processBranch(const Stmt *Condition,
27782776
// Check for NULL conditions; e.g. "for(;;)"
27792777
if (!Condition) {
27802778
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
2781-
NullCondBldr.markInfeasible(false);
27822779
NullCondBldr.generateNode(Pred->getState(), true, Pred);
27832780
return;
27842781
}
@@ -2798,40 +2795,25 @@ void ExprEngine::processBranch(const Stmt *Condition,
27982795
if (CheckersOutSet.empty())
27992796
return;
28002797

2801-
BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2798+
BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
28022799
for (ExplodedNode *PredN : CheckersOutSet) {
28032800
if (PredN->isSink())
28042801
continue;
28052802

28062803
ProgramStateRef PrevState = PredN->getState();
28072804

2808-
ProgramStateRef StTrue, StFalse;
2805+
ProgramStateRef StTrue = PrevState, StFalse = PrevState;
28092806
if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))
28102807
std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2811-
else {
2812-
assert(!isa<ObjCForCollectionStmt>(Condition));
2813-
builder.generateNode(PrevState, true, PredN);
2814-
builder.generateNode(PrevState, false, PredN);
2815-
continue;
2816-
}
2808+
28172809
if (StTrue && StFalse)
28182810
assert(!isa<ObjCForCollectionStmt>(Condition));
28192811

2820-
// Process the true branch.
2821-
if (builder.isFeasible(true)) {
2822-
if (StTrue)
2823-
builder.generateNode(StTrue, true, PredN);
2824-
else
2825-
builder.markInfeasible(true);
2826-
}
2812+
if (StTrue)
2813+
Builder.generateNode(StTrue, true, PredN);
28272814

2828-
// Process the false branch.
2829-
if (builder.isFeasible(false)) {
2830-
if (StFalse)
2831-
builder.generateNode(StFalse, false, PredN);
2832-
else
2833-
builder.markInfeasible(false);
2834-
}
2815+
if (StFalse)
2816+
Builder.generateNode(StFalse, false, PredN);
28352817
}
28362818
currBldrCtx = nullptr;
28372819
}
@@ -2853,14 +2835,13 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
28532835
const auto *VD = cast<VarDecl>(DS->getSingleDecl());
28542836
ProgramStateRef state = Pred->getState();
28552837
bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2856-
BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
2838+
BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);
28572839

28582840
if (!initHasRun) {
28592841
state = state->add<InitializedGlobalsSet>(VD);
28602842
}
28612843

2862-
builder.generateNode(state, initHasRun, Pred);
2863-
builder.markInfeasible(!initHasRun);
2844+
Builder.generateNode(state, initHasRun, Pred);
28642845

28652846
currBldrCtx = nullptr;
28662847
}

0 commit comments

Comments
 (0)