Skip to content

Commit 9ed4a94

Browse files
committed
[clang] Expose unreachable fallthrough annotation warning
The Linux kernel has a macro called IS_ENABLED(), which evaluates to a constant 1 or 0 based on Kconfig selections, allowing C code to be unconditionally enabled or disabled at build time. For example: int foo(struct *a, int b) { switch (b) { case 1: if (a->flag || !IS_ENABLED(CONFIG_64BIT)) return 1; __attribute__((fallthrough)); case 2: return 2; default: return 3; } } There is an unreachable warning about the fallthrough annotation in the first case because !IS_ENABLED(CONFIG_64BIT) can be evaluated to 1, which looks like return 1; __attribute__((fallthrough)); to clang. This type of warning is pointless for the Linux kernel because it does this trick all over the place due to the sheer number of configuration options that it has. Add -Wunreachable-code-fallthrough, enabled under -Wunreachable-code, so that projects that want to warn on unreachable code get this warning but projects that do not care about unreachable code can still use -Wimplicit-fallthrough without having to make changes to their code base. Fixes PR51094. Reviewed By: aaron.ballman, nickdesaulniers Differential Revision: https://reviews.llvm.org/D107933
1 parent e2c97d4 commit 9ed4a94

File tree

5 files changed

+29
-7
lines changed

5 files changed

+29
-7
lines changed

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,10 @@ def ReservedIdentifier : DiagGroup<"reserved-identifier",
821821
// under separate flags.
822822
//
823823
def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">;
824+
def UnreachableCodeFallthrough : DiagGroup<"unreachable-code-fallthrough">;
824825
def UnreachableCode : DiagGroup<"unreachable-code",
825-
[UnreachableCodeLoopIncrement]>;
826+
[UnreachableCodeLoopIncrement,
827+
UnreachableCodeFallthrough]>;
826828
def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">;
827829
def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">;
828830
def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive",

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,9 @@ def warn_unreachable_return : Warning<
682682
def warn_unreachable_loop_increment : Warning<
683683
"loop will run at most once (loop increment never executed)">,
684684
InGroup<UnreachableCodeLoopIncrement>, DefaultIgnore;
685+
def warn_unreachable_fallthrough_attr : Warning<
686+
"fallthrough annotation in unreachable code">,
687+
InGroup<UnreachableCodeFallthrough>, DefaultIgnore;
685688
def note_unreachable_silence : Note<
686689
"silence by adding parentheses to mark code as explicitly dead">;
687690

@@ -9578,9 +9581,6 @@ def err_fallthrough_attr_outside_switch : Error<
95789581
"fallthrough annotation is outside switch statement">;
95799582
def err_fallthrough_attr_invalid_placement : Error<
95809583
"fallthrough annotation does not directly precede switch label">;
9581-
def warn_fallthrough_attr_unreachable : Warning<
9582-
"fallthrough annotation in unreachable code">,
9583-
InGroup<ImplicitFallthrough>, DefaultIgnore;
95849584

95859585
def warn_unreachable_default : Warning<
95869586
"default label in switch which covers all enumeration values">,

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ namespace {
11251125
// unreachable in all instantiations of the template.
11261126
if (!IsTemplateInstantiation)
11271127
S.Diag(AS->getBeginLoc(),
1128-
diag::warn_fallthrough_attr_unreachable);
1128+
diag::warn_unreachable_fallthrough_attr);
11291129
markFallthroughVisited(AS);
11301130
++AnnotatedCnt;
11311131
break;

clang/test/SemaCXX/P30636.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough -Wunreachable-code-fallthrough %s
22
// expected-no-diagnostics
33

44
template<bool param>

clang/test/SemaCXX/switch-implicit-fallthrough.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough -Wunreachable-code-fallthrough %s
22

33

44
int fallthrough(int n) {
@@ -193,6 +193,26 @@ int fallthrough_position(int n) {
193193
;
194194
}
195195

196+
#pragma clang diagnostic push
197+
#pragma clang diagnostic ignored "-Wunreachable-code-fallthrough"
198+
switch (n) {
199+
n += 300;
200+
[[clang::fallthrough]]; // no warning here
201+
case 221:
202+
return 1;
203+
[[clang::fallthrough]]; // no warning here
204+
case 222:
205+
return 2;
206+
__attribute__((fallthrough)); // no warning here
207+
case 223:
208+
if (1)
209+
return 3;
210+
__attribute__((fallthrough)); // no warning here
211+
case 224:
212+
n += 400;
213+
}
214+
#pragma clang diagnostic pop
215+
196216
long p = static_cast<long>(n) * n;
197217
switch (sizeof(p)) {
198218
case 9:

0 commit comments

Comments
 (0)