xbolva00 created this revision. xbolva00 added reviewers: aaron.ballman, rsmith, rjmccall. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Detects unreachable statements in switches. GCC supports this warning too, on by default. Repository: rC Clang https://reviews.llvm.org/D63139 Files: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaStmt.cpp test/Sema/switch_unreachable.c test/SemaCXX/switch_unreachable.cpp
Index: test/SemaCXX/switch_unreachable.cpp =================================================================== --- test/SemaCXX/switch_unreachable.cpp +++ test/SemaCXX/switch_unreachable.cpp @@ -0,0 +1,103 @@ +// 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; + if (x == 7) + goto label; + if (x == 3) + goto label2; + if (x == 4) + goto label3; + if (x == 1) + goto label4; + + 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 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; + } +} Index: test/Sema/switch_unreachable.c =================================================================== --- test/Sema/switch_unreachable.c +++ test/Sema/switch_unreachable.c @@ -0,0 +1,97 @@ +// 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; + if (x == 7) + goto label; + if (x == 3) + goto label2; + if (x == 4) + goto label3; + if (x == 1) + goto label4; + + 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; + } +} Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -861,6 +861,16 @@ typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy; CaseRangesTy CaseRanges; + CompoundStmt *CS = dyn_cast<CompoundStmt>(BodyStmt); + if (CS && !CS->body_empty()) { + for (auto It = CS->body_begin(); It != CS->body_end(); ++It) { + auto *S = *It; + if (isa<LabelStmt>(S) || isa<CaseStmt>(S) || isa<DefaultStmt>(S)) + break; + Diag(S->getBeginLoc(), diag::warn_unreachable_stmt_in_switch); + } + } + DefaultStmt *TheDefaultStmt = nullptr; bool CaseListIsErroneous = false; 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<SwitchUnreachable>, DefaultIgnore; def warn_bool_switch_condition : Warning< "switch condition has boolean value">, InGroup<SwitchBool>; def warn_case_value_overflow : Warning< 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]>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits