From: David Majnemer Date: Tue, 4 Jun 2013 17:38:44 +0000 (+0000) Subject: Analysis: Add a CFG successor to a SwitchStmt if it is both empty and fully covered X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a1551fa14728891bf8e325d3eb686ed404cd8b2;p=clang Analysis: Add a CFG successor to a SwitchStmt if it is both empty and fully covered Consider the case where a SwitchStmt satisfied isAllEnumCasesCovered() as well as having no cases at all (i.e. the enum it covers has no enumerators). In this case, we should add a successor to repair the CFG. This fixes PR16212. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183237 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index e06e661750..9945dcb36c 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -2671,9 +2671,15 @@ CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { // If we have no "default:" case, the default transition is to the code // following the switch body. Moreover, take into account if all the // cases of a switch are covered (e.g., switching on an enum value). + // + // Note: We add a successor to a switch that is considered covered yet has no + // case statements if the enumeration has no enumerators. + bool SwitchAlwaysHasSuccessor = false; + SwitchAlwaysHasSuccessor |= switchExclusivelyCovered; + SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() && + Terminator->getSwitchCaseList(); addSuccessor(SwitchTerminatedBlock, - switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() - ? 0 : DefaultCaseBlock); + SwitchAlwaysHasSuccessor ? 0 : DefaultCaseBlock); // Add the terminator and condition in the switch block. SwitchTerminatedBlock->setTerminator(Terminator); diff --git a/test/Analysis/cfg.cpp b/test/Analysis/cfg.cpp index 0587057d72..c2ec2e9bec 100644 --- a/test/Analysis/cfg.cpp +++ b/test/Analysis/cfg.cpp @@ -66,3 +66,19 @@ void checkDeclStmts() { static_assert(1, "abc"); } + +// CHECK: ENTRY +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// CHECK-NEXT: 1: e +// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, enum EmptyE) +// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, IntegralCast, int) +// CHECK-NEXT: T: switch [B1.3] +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +enum EmptyE {}; +void F(EmptyE e) { + switch (e) {} +}