nathanchance created this revision. nathanchance added reviewers: dblaikie, rsmith, nickdesaulniers. nathanchance requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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 -Wimplicit-fallthrough-unreachable, which is default enabled with -Wimplicit-fallthrough to keep the status quo but allows projects to opt out of the warning when they know these annotations may be unreachable in certain conditions. Fixes PR51094. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D107933 Files: clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/test/SemaCXX/switch-implicit-fallthrough.cpp Index: clang/test/SemaCXX/switch-implicit-fallthrough.cpp =================================================================== --- clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ clang/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -193,6 +193,28 @@ ; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wimplicit-fallthrough-unreachable" + switch (n) { + n += 300; + [[clang::fallthrough]]; // no warning here + case 221: + return 1; + [[clang::fallthrough]]; // no warning here + case 222: + return 2; + __attribute__((fallthrough)); // no warning here + case 223: + if (1) + return 3; + __attribute__((fallthrough)); // no warning here + case 224: + n += 400; + case 225: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + ; + } +#pragma clang diagnostic pop + long p = static_cast<long>(n) * n; switch (sizeof(p)) { case 9: Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9580,7 +9580,7 @@ "fallthrough annotation does not directly precede switch label">; def warn_fallthrough_attr_unreachable : Warning< "fallthrough annotation in unreachable code">, - InGroup<ImplicitFallthrough>, DefaultIgnore; + InGroup<ImplicitFallthroughUnreachable>, DefaultIgnore; def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -671,8 +671,11 @@ def Switch : DiagGroup<"switch">; def ImplicitFallthroughPerFunction : DiagGroup<"implicit-fallthrough-per-function">; +def ImplicitFallthroughUnreachable : + DiagGroup<"implicit-fallthrough-unreachable">; def ImplicitFallthrough : DiagGroup<"implicit-fallthrough", - [ImplicitFallthroughPerFunction]>; + [ImplicitFallthroughPerFunction, + ImplicitFallthroughUnreachable]>; def InvalidPPToken : DiagGroup<"invalid-pp-token">; def Trigraphs : DiagGroup<"trigraphs">;
Index: clang/test/SemaCXX/switch-implicit-fallthrough.cpp =================================================================== --- clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ clang/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -193,6 +193,28 @@ ; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wimplicit-fallthrough-unreachable" + switch (n) { + n += 300; + [[clang::fallthrough]]; // no warning here + case 221: + return 1; + [[clang::fallthrough]]; // no warning here + case 222: + return 2; + __attribute__((fallthrough)); // no warning here + case 223: + if (1) + return 3; + __attribute__((fallthrough)); // no warning here + case 224: + n += 400; + case 225: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + ; + } +#pragma clang diagnostic pop + long p = static_cast<long>(n) * n; switch (sizeof(p)) { case 9: Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9580,7 +9580,7 @@ "fallthrough annotation does not directly precede switch label">; def warn_fallthrough_attr_unreachable : Warning< "fallthrough annotation in unreachable code">, - InGroup<ImplicitFallthrough>, DefaultIgnore; + InGroup<ImplicitFallthroughUnreachable>, DefaultIgnore; def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -671,8 +671,11 @@ def Switch : DiagGroup<"switch">; def ImplicitFallthroughPerFunction : DiagGroup<"implicit-fallthrough-per-function">; +def ImplicitFallthroughUnreachable : + DiagGroup<"implicit-fallthrough-unreachable">; def ImplicitFallthrough : DiagGroup<"implicit-fallthrough", - [ImplicitFallthroughPerFunction]>; + [ImplicitFallthroughPerFunction, + ImplicitFallthroughUnreachable]>; def InvalidPPToken : DiagGroup<"invalid-pp-token">; def Trigraphs : DiagGroup<"trigraphs">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits