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;