xbolva00 updated this revision to Diff 205295.
xbolva00 added a comment.

Addressed some notes. Thanks.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63139/new/

https://reviews.llvm.org/D63139

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaStmt.cpp
  test/Sema/implicit-decl-c90.c
  test/SemaCXX/array-bounds.cpp
  test/SemaCXX/warn-unreachable-stmt-switch.cpp

Index: test/SemaCXX/warn-unreachable-stmt-switch.cpp
===================================================================
--- test/SemaCXX/warn-unreachable-stmt-switch.cpp
+++ test/SemaCXX/warn-unreachable-stmt-switch.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wswitch-unreachable %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wswitch-unreachable %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify  %s
+
+void g(int x);
+
+void foo(int x) {
+  int b = 0;
+  switch (x) {
+  label:
+  case 4:
+    break;
+  default:
+    return;
+  }
+
+  switch (x) {
+    x++; // expected-warning {{statement will be never executed}}
+  label2:
+  case 4:
+    break;
+  default:
+    return;
+  }
+
+  switch (x) {
+  label3:
+    x++;
+  case 4:
+    break;
+  default:
+    return;
+  }
+
+  switch (x) {
+  case 4:
+    return;
+  }
+
+  switch (x) {
+    b = x; // expected-warning {{statement will be never executed}}
+  case 7:
+    g(b);
+    break;
+  }
+
+  switch (x) {
+    ;
+  case 7:
+    g(b);
+    break;
+  }
+
+  switch (x) {
+    break; // expected-warning {{statement will be never executed}}
+  case 7:
+    break;
+  }
+
+  switch (x) {
+    return; // expected-warning {{statement will be never executed}}
+  case 7:
+    break;
+  }
+
+  switch (x) {
+    x++;  // expected-warning {{statement will be never executed}}
+    g(x); // expected-warning {{statement will be never executed}}
+  case 7:
+    break;
+  }
+
+  switch (x) {
+    x++; // expected-warning {{statement will be never executed}}
+  label4:
+    g(x);
+  case 7:
+    break;
+  }
+
+  switch (x) {
+    g(x); // expected-warning {{statement will be never executed}}
+  case 1:
+    break;
+  case 2:
+    break;
+  }
+
+  switch (x) {
+    g(x); // expected-warning {{statement will be never executed}}
+  case 1:
+  case 2:
+  case 3:
+    break;
+  }
+
+  switch (x) {
+  case 1:
+    break;
+  case 2:
+    break;
+  }
+
+  switch (x) {
+  case 1:
+    break;
+  default:
+    break;
+  }
+
+  switch (x) {
+    b = x; // expected-warning {{statement will be never executed}}
+  }
+
+  switch (x) {
+    g(x); // expected-warning {{statement will be never executed}}
+  }
+
+  switch (x)
+    b = x; // expected-warning {{statement will be never executed}}
+
+  switch (x)
+    g(x); // expected-warning {{statement will be never executed}}
+
+  switch (x)
+  label5:
+    g(x);
+
+  switch (x) {
+  label6:
+    g(x);
+  }
+
+  switch (x)
+  case 5:
+    g(x);
+
+  switch (x) {
+  case 5:
+    g(x);
+  }
+
+  switch (x)
+  default:
+    g(x);
+
+  switch (x) {
+  default:
+    g(x);
+  }
+}
Index: test/SemaCXX/array-bounds.cpp
===================================================================
--- test/SemaCXX/array-bounds.cpp
+++ test/SemaCXX/array-bounds.cpp
@@ -164,6 +164,7 @@
 static enum enumB myVal = enumB_X;
 void test_nested_switch() {
   switch (enumA_E) { // expected-warning {{no case matching constant}}
+    // expected-warning@+1 {{statement will be never executed}}
     switch (myVal) { // expected-warning {{enumeration values 'enumB_X' and 'enumB_Z' not handled in switch}}
       case enumB_Y: ;
     }
Index: test/Sema/implicit-decl-c90.c
===================================================================
--- test/Sema/implicit-decl-c90.c
+++ test/Sema/implicit-decl-c90.c
@@ -15,7 +15,7 @@
 void t1(int x) {
   int (*p)();
   switch (x) {
-    g();
+    g(); // expected-warning {{statement will be never executed}}
   case 0:
     x = h() + 1;
     break;
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -723,7 +723,8 @@
 /// Check the specified case value is in range for the given unpromoted switch
 /// type.
 static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
-                           unsigned UnpromotedWidth, bool UnpromotedSign) {
+                           unsigned UnpromotedWidth, bool UnpromotedSign,
+                           bool &CaseListIsErroneous) {
   // In C++11 onwards, this is checked by the language rules.
   if (S.getLangOpts().CPlusPlus11)
     return;
@@ -738,9 +739,11 @@
     // FIXME: Use different diagnostics for overflow  in conversion to promoted
     // type versus "switch expression cannot have this value". Use proper
     // IntRange checking rather than just looking at the unpromoted type here.
-    if (ConvVal != Val)
-      S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10)
-                                                  << ConvVal.toString(10);
+    if (ConvVal != Val) {
+      CaseListIsErroneous = true;
+      S.Diag(Loc, diag::warn_case_value_overflow)
+          << Val.toString(10) << ConvVal.toString(10);
+    }
   }
 }
 
@@ -819,6 +822,19 @@
   if (!BodyStmt) return StmtError();
   SS->setBody(BodyStmt, SwitchLoc);
 
+  if (const auto *CS = dyn_cast<CompoundStmt>(BodyStmt)) {
+    for (const auto *S : CS->body()) {
+      if (isa<NullStmt>(S))
+        continue;
+      if (isa<LabelStmt>(S) || isa<CaseStmt>(S) || isa<DefaultStmt>(S))
+        break;
+      Diag(S->getBeginLoc(), diag::warn_unreachable_stmt_in_switch);
+    }
+  } else if (!isa<LabelStmt>(BodyStmt) && !isa<CaseStmt>(BodyStmt) &&
+             !isa<DefaultStmt>(BodyStmt) && !isa<NullStmt>(BodyStmt)) {
+    Diag(BodyStmt->getBeginLoc(), diag::warn_unreachable_stmt_in_switch);
+  }
+
   Expr *CondExpr = SS->getCond();
   if (!CondExpr) return StmtError();
 
@@ -900,7 +916,7 @@
       // Check the unconverted value is within the range of possible values of
       // the switch expression.
       checkCaseValue(*this, Lo->getBeginLoc(), LoVal, CondWidthBeforePromotion,
-                     CondIsSignedBeforePromotion);
+                     CondIsSignedBeforePromotion, CaseListIsErroneous);
 
       // FIXME: This duplicates the check performed for warn_not_in_enum below.
       checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
@@ -1003,7 +1019,8 @@
         // Check the unconverted value is within the range of possible values of
         // the switch expression.
         checkCaseValue(*this, Hi->getBeginLoc(), HiVal,
-                       CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+                       CondWidthBeforePromotion, CondIsSignedBeforePromotion,
+                       CaseListIsErroneous);
 
         // Convert the value to the same width/sign as the condition.
         AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -8188,6 +8188,8 @@
 def err_default_not_in_switch : Error<
   "'default' statement not in switch statement">;
 def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
+def warn_unreachable_stmt_in_switch : Warning<
+  "statement will be never executed">, InGroup<DiagGroup<"switch-unreachable">>;
 def warn_bool_switch_condition : Warning<
   "switch condition has boolean value">, InGroup<SwitchBool>;
 def warn_case_value_overflow : Warning<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to