@@ -542,6 +542,7 @@ class CFGBuilder {
542
542
// Visitors to walk an AST and construct the CFG.
543
543
CFGBlock *VisitInitListExpr (InitListExpr *ILE, AddStmtChoice asc);
544
544
CFGBlock *VisitAddrLabelExpr (AddrLabelExpr *A, AddStmtChoice asc);
545
+ CFGBlock *VisitAttributedStmt (AttributedStmt *A, AddStmtChoice asc);
545
546
CFGBlock *VisitBinaryOperator (BinaryOperator *B, AddStmtChoice asc);
546
547
CFGBlock *VisitBreakStmt (BreakStmt *B);
547
548
CFGBlock *VisitCallExpr (CallExpr *C, AddStmtChoice asc);
@@ -2149,6 +2150,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2149
2150
case Stmt::InitListExprClass:
2150
2151
return VisitInitListExpr (cast<InitListExpr>(S), asc);
2151
2152
2153
+ case Stmt::AttributedStmtClass:
2154
+ return VisitAttributedStmt (cast<AttributedStmt>(S), asc);
2155
+
2152
2156
case Stmt::AddrLabelExprClass:
2153
2157
return VisitAddrLabelExpr (cast<AddrLabelExpr>(S), asc);
2154
2158
@@ -2398,8 +2402,32 @@ CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2398
2402
return Block;
2399
2403
}
2400
2404
2401
- CFGBlock *CFGBuilder::VisitUnaryOperator (UnaryOperator *U,
2402
- AddStmtChoice asc) {
2405
+ static bool isFallthroughStatement (const AttributedStmt *A) {
2406
+ bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->getAttrs ());
2407
+ assert ((!isFallthrough || isa<NullStmt>(A->getSubStmt ())) &&
2408
+ " expected fallthrough not to have children" );
2409
+ return isFallthrough;
2410
+ }
2411
+
2412
+ CFGBlock *CFGBuilder::VisitAttributedStmt (AttributedStmt *A,
2413
+ AddStmtChoice asc) {
2414
+ // AttributedStmts for [[likely]] can have arbitrary statements as children,
2415
+ // and the current visitation order here would add the AttributedStmts
2416
+ // for [[likely]] after the child nodes, which is undesirable: For example,
2417
+ // if the child contains an unconditional return, the [[likely]] would be
2418
+ // considered unreachable.
2419
+ // So only add the AttributedStmt for FallThrough, which has CFG effects and
2420
+ // also no children, and omit the others. None of the other current StmtAttrs
2421
+ // have semantic meaning for the CFG.
2422
+ if (isFallthroughStatement (A) && asc.alwaysAdd (*this , A)) {
2423
+ autoCreateBlock ();
2424
+ appendStmt (Block, A);
2425
+ }
2426
+
2427
+ return VisitChildren (A);
2428
+ }
2429
+
2430
+ CFGBlock *CFGBuilder::VisitUnaryOperator (UnaryOperator *U, AddStmtChoice asc) {
2403
2431
if (asc.alwaysAdd (*this , U)) {
2404
2432
autoCreateBlock ();
2405
2433
appendStmt (Block, U);
@@ -3333,7 +3361,7 @@ CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3333
3361
// Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
3334
3362
// used to avoid adding "Succ" again.
3335
3363
BackpatchBlocks.push_back (JumpSource (Succ, ScopePos));
3336
- return Block ;
3364
+ return VisitChildren (G) ;
3337
3365
}
3338
3366
3339
3367
CFGBlock *CFGBuilder::VisitForStmt (ForStmt *F) {
0 commit comments