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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits