@@ -542,6 +542,7 @@ class CFGBuilder {
542542 // Visitors to walk an AST and construct the CFG.
543543 CFGBlock *VisitInitListExpr (InitListExpr *ILE, AddStmtChoice asc);
544544 CFGBlock *VisitAddrLabelExpr (AddrLabelExpr *A, AddStmtChoice asc);
545+ CFGBlock *VisitAttributedStmt (AttributedStmt *A, AddStmtChoice asc);
545546 CFGBlock *VisitBinaryOperator (BinaryOperator *B, AddStmtChoice asc);
546547 CFGBlock *VisitBreakStmt (BreakStmt *B);
547548 CFGBlock *VisitCallExpr (CallExpr *C, AddStmtChoice asc);
@@ -2149,6 +2150,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
21492150 case Stmt::InitListExprClass:
21502151 return VisitInitListExpr (cast<InitListExpr>(S), asc);
21512152
2153+ case Stmt::AttributedStmtClass:
2154+ return VisitAttributedStmt (cast<AttributedStmt>(S), asc);
2155+
21522156 case Stmt::AddrLabelExprClass:
21532157 return VisitAddrLabelExpr (cast<AddrLabelExpr>(S), asc);
21542158
@@ -2398,8 +2402,32 @@ CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
23982402 return Block;
23992403}
24002404
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) {
24032431 if (asc.alwaysAdd (*this , U)) {
24042432 autoCreateBlock ();
24052433 appendStmt (Block, U);
@@ -3333,7 +3361,7 @@ CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
33333361 // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
33343362 // used to avoid adding "Succ" again.
33353363 BackpatchBlocks.push_back (JumpSource (Succ, ScopePos));
3336- return Block ;
3364+ return VisitChildren (G) ;
33373365}
33383366
33393367CFGBlock *CFGBuilder::VisitForStmt (ForStmt *F) {
0 commit comments