]> granicus.if.org Git - clang/commitdiff
Analysis: Add a CFG successor to a SwitchStmt if it is both empty and fully covered
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 4 Jun 2013 17:38:44 +0000 (17:38 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 4 Jun 2013 17:38:44 +0000 (17:38 +0000)
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

lib/Analysis/CFG.cpp
test/Analysis/cfg.cpp

index e06e66175089ae988083a2ab4020c8df8f7e4aaf..9945dcb36ce8f091661451bb808dbf7a154635c8 100644 (file)
@@ -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);
index 0587057d7244d4f4c78ecb57b5c10117c2afd4a7..c2ec2e9bec2cd34dc27e1d314ddf8dc0551e6852 100644 (file)
@@ -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) {}
+}