1212// ===----------------------------------------------------------------------===//
1313
1414#include < algorithm>
15- #include < memory>
1615#include < optional>
1716#include < system_error>
1817#include < utility>
3332#include " clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
3433#include " clang/Analysis/FlowSensitive/Value.h"
3534#include " llvm/ADT/ArrayRef.h"
36- #include " llvm/ADT/DenseSet.h"
3735#include " llvm/ADT/STLExtras.h"
36+ #include " llvm/ADT/SmallBitVector.h"
3837#include " llvm/Support/Debug.h"
3938#include " llvm/Support/Error.h"
4039
@@ -53,19 +52,14 @@ static int blockIndexInPredecessor(const CFGBlock &Pred,
5352 return BlockPos - Pred.succ_begin ();
5453}
5554
56- static bool isLoopHead (const CFGBlock &B) {
57- if (const auto *T = B.getTerminatorStmt ())
58- switch (T->getStmtClass ()) {
59- case Stmt::WhileStmtClass:
60- case Stmt::DoStmtClass:
61- case Stmt::ForStmtClass:
62- case Stmt::CXXForRangeStmtClass:
63- return true ;
64- default :
65- return false ;
66- }
67-
68- return false ;
55+ // A "backedge" node is a block introduced in the CFG exclusively to indicate a
56+ // loop backedge. They are exactly identified by the presence of a non-null
57+ // pointer to the entry block of the loop condition. Note that this is not
58+ // necessarily the block with the loop statement as terminator, because
59+ // short-circuit operators will result in multiple blocks encoding the loop
60+ // condition, only one of which will contain the loop statement as terminator.
61+ static bool isBackedgeNode (const CFGBlock &B) {
62+ return B.getLoopTarget () != nullptr ;
6963}
7064
7165namespace {
@@ -502,14 +496,15 @@ runTypeErasedDataflowAnalysis(
502496 PostVisitCFG) {
503497 PrettyStackTraceAnalysis CrashInfo (CFCtx, " runTypeErasedDataflowAnalysis" );
504498
505- PostOrderCFGView POV (&CFCtx.getCFG ());
506- ForwardDataflowWorklist Worklist (CFCtx.getCFG (), &POV);
499+ const clang::CFG &CFG = CFCtx.getCFG ();
500+ PostOrderCFGView POV (&CFG);
501+ ForwardDataflowWorklist Worklist (CFG, &POV);
507502
508503 std::vector<std::optional<TypeErasedDataflowAnalysisState>> BlockStates (
509- CFCtx. getCFG () .size ());
504+ CFG .size ());
510505
511506 // The entry basic block doesn't contain statements so it can be skipped.
512- const CFGBlock &Entry = CFCtx. getCFG () .getEntry ();
507+ const CFGBlock &Entry = CFG .getEntry ();
513508 BlockStates[Entry.getBlockID ()] = {Analysis.typeErasedInitialElement (),
514509 InitEnv.fork ()};
515510 Worklist.enqueueSuccessors (&Entry);
@@ -553,7 +548,7 @@ runTypeErasedDataflowAnalysis(
553548 llvm::errs () << " Old Env:\n " ;
554549 OldBlockState->Env .dump ();
555550 });
556- if (isLoopHead (*Block)) {
551+ if (isBackedgeNode (*Block)) {
557552 LatticeJoinEffect Effect1 = Analysis.widenTypeErased (
558553 NewBlockState.Lattice , OldBlockState->Lattice );
559554 LatticeJoinEffect Effect2 =
0 commit comments