Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -458,7 +458,6 @@ def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; def : DiagGroup<"stack-protector">; -def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; @@ -537,6 +536,7 @@ def ObjCCStringFormat : DiagGroup<"cstring-format-directive">; def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchBool : DiagGroup<"switch-bool">; +def SwitchDefault : DiagGroup<"switch-default">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch">; def EnumCompareSwitch : DiagGroup<"enum-compare-switch">; @@ -842,7 +842,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, SwitchDefault]>; // 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 @@ -8201,6 +8201,10 @@ def warn_break_binds_to_switch : Warning< "'break' is bound to loop, GCC binds it to switch">, InGroup; +def warn_no_cases_in_switch : Warning< + "switch has no default and case labels">, InGroup, DefaultIgnore; +def warn_default_only_in_switch : Warning< + "switch contains only default label">, InGroup, DefaultIgnore; 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">; Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -865,8 +865,13 @@ bool CaseListIsErroneous = false; - for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; - SC = SC->getNextSwitchCase()) { + SwitchCase *SC = SS->getSwitchCaseList(); + if (!SC) + Diag(SS->getBeginLoc(), diag::warn_no_cases_in_switch); + else if (isa(SC) && !SC->getNextSwitchCase()) + Diag(SC->getBeginLoc(), diag::warn_default_only_in_switch); + + for (; SC && !HasDependentValue; SC = SC->getNextSwitchCase()) { if (DefaultStmt *DS = dyn_cast(SC)) { if (TheDefaultStmt) { Index: test/Sema/switch-availability.c =================================================================== --- test/Sema/switch-availability.c +++ test/Sema/switch-availability.c @@ -5,7 +5,7 @@ }; void testSwitchOne(enum SwitchOne so) { - switch (so) {} // no warning + switch (so) {} // expected-warning {{switch has no default and case labels}} } enum SwitchTwo { @@ -15,6 +15,7 @@ }; void testSwitchTwo(enum SwitchTwo st) { + // expected-warning@+1 {{switch has no default and case labels}} switch (st) {} // expected-warning{{enumeration values 'Vim' and 'Emacs' not handled in switch}} } @@ -23,5 +24,6 @@ }; void testSwitchThree(enum SwitchThree st) { + // expected-warning@+1 {{switch has no default and case labels}} switch (st) {} // expected-warning{{enumeration value 'New' not handled in switch}} } Index: test/SemaCXX/switch_default.cpp =================================================================== --- test/SemaCXX/switch_default.cpp +++ test/SemaCXX/switch_default.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wswitch-default %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wswitch-default %s +// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s + +void test(int x) { + switch (x) { + default: // expected-warning {{switch contains only default label}} + break; + } + + switch (x) { + default: // expected-warning {{switch contains only default label}} + x++; + } + + switch (x) { + default:; // expected-warning {{switch contains only default label}} + } + + switch (x) + default: // expected-warning {{switch contains only default label}} + break; + + switch (x) { + default: + return; + case 1: + break; + } + + switch (x) { + case 1: + break; + default: + return; + } +} Index: test/SemaCXX/uninitialized.cpp =================================================================== --- test/SemaCXX/uninitialized.cpp +++ test/SemaCXX/uninitialized.cpp @@ -1444,8 +1444,8 @@ if (int n = 0; (n == k || k > 5)) {} if (int n; (n == k || k > 5)) {} // expected-warning {{uninitialized}} expected-note {{initialize}} - + // expected-warning@+1 {{switch has no default and case labels}} switch (int n = 0; (n == k || k > 5)) {} // expected-warning {{boolean}} - + // expected-warning@+1 {{switch has no default and case labels}} switch (int n; (n == k || k > 5)) {} // expected-warning {{uninitialized}} expected-note {{initialize}} expected-warning {{boolean}} }