Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -538,6 +538,7 @@ def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchBool : DiagGroup<"switch-bool">; def SwitchEnum : DiagGroup<"switch-enum">; +def SwitchUnreachable : DiagGroup<"switch-unreachable">; def Switch : DiagGroup<"switch">; def EnumCompareSwitch : DiagGroup<"enum-compare-switch">; def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch]>; @@ -842,7 +843,7 @@ // Note that putting warnings in -Wall will not disable them by default. If a // warning should be active _only_ when -Wall is passed in, mark it as // DefaultIgnore in addition to putting it here. -def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>; +def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool, SwitchUnreachable]>; // Warnings that should be in clang-cl /w4. def : DiagGroup<"CL4", [All, Extra]>; 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, DefaultIgnore; def warn_bool_switch_condition : Warning< "switch condition has boolean value">, InGroup; def warn_case_value_overflow : Warning< Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -861,6 +861,20 @@ typedef std::vector > CaseRangesTy; CaseRangesTy CaseRanges; + if (CompoundStmt *CS = dyn_cast(BodyStmt)) { + for (auto It = CS->body_begin(); It != CS->body_end(); ++It) { + auto *S = *It; + if (isa(S) || isa(S) || isa(S)) + break; + Diag(S->getBeginLoc(), diag::warn_unreachable_stmt_in_switch); + } + } else if (isa(BodyStmt) || isa(BodyStmt) || + isa(BodyStmt)) { + // No warning + } else { + Diag(BodyStmt->getBeginLoc(), diag::warn_unreachable_stmt_in_switch); + } + DefaultStmt *TheDefaultStmt = nullptr; bool CaseListIsErroneous = false; Index: test/Sema/switch_unreachable.c =================================================================== --- test/Sema/switch_unreachable.c +++ test/Sema/switch_unreachable.c @@ -0,0 +1,143 @@ +// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wswitch-unreachable %s +// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %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) { + 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) { + case 5: + g(x); + } +} Index: test/SemaCXX/switch_unreachable.cpp =================================================================== --- test/SemaCXX/switch_unreachable.cpp +++ test/SemaCXX/switch_unreachable.cpp @@ -0,0 +1,143 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wswitch-unreachable %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %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) { + 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); + } +}