Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1156,7 +1156,7 @@ def FallThrough : StmtAttr { let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">, - CXX11<"clang", "fallthrough">]; + CXX11<"clang", "fallthrough">, GCC<"fallthrough">]; // let Subjects = [NullStmt]; let Documentation = [FallthroughDocs]; } Index: lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- lib/Sema/AnalysisBasedWarnings.cpp +++ lib/Sema/AnalysisBasedWarnings.cpp @@ -1215,7 +1215,7 @@ tok::r_square, tok::r_square }; - bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17; + bool PreferClangAttr = !PP.getLangOpts().CPlusPlus17 && !PP.getLangOpts().C2x; StringRef MacroName; if (PreferClangAttr) @@ -1224,24 +1224,19 @@ MacroName = PP.getLastMacroWithSpelling(Loc, FallthroughTokens); if (MacroName.empty() && !PreferClangAttr) MacroName = PP.getLastMacroWithSpelling(Loc, ClangFallthroughTokens); - if (MacroName.empty()) - MacroName = PreferClangAttr ? "[[clang::fallthrough]]" : "[[fallthrough]]"; + if (MacroName.empty()) { + if (!PreferClangAttr) + MacroName = "[[fallthrough]]"; + else if (PP.getLangOpts().CPlusPlus) + MacroName = "[[clang::fallthrough]]"; + else + MacroName = "__attribute__ ((fallthrough))"; + } return MacroName; } static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction) { - // Only perform this analysis when using [[]] attributes. There is no good - // workflow for this warning when not using C++11. There is no good way to - // silence the warning (no attribute is available) unless we are using - // [[]] attributes. One could use pragmas to silence the warning, but as a - // general solution that is gross and not in the spirit of this warning. - // - // NOTE: This an intermediate solution. There are on-going discussions on - // how to properly support this warning outside of C++11 with an annotation. - if (!AC.getASTContext().getLangOpts().DoubleSquareBracketAttributes) - return; - FallthroughMapper FM(S); FM.TraverseStmt(AC.getBody()); @@ -1281,7 +1276,8 @@ SourceLocation L = Label->getBeginLoc(); if (L.isMacroID()) continue; - if (S.getLangOpts().CPlusPlus11) { + if (S.getLangOpts().CPlusPlus11 || + (!S.getLangOpts().CPlusPlus && !S.getLangOpts().ObjC)) { const Stmt *Term = B->getTerminatorStmt(); // Skip empty cases. while (B->empty() && !Term && B->succ_size() == 1) { Index: test/Sema/fallthrough-attr.c =================================================================== --- test/Sema/fallthrough-attr.c +++ test/Sema/fallthrough-attr.c @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -std=gnu89 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu99 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c99 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c2x -DC2X -verify -Wimplicit-fallthrough %s + +int fallthrough_attribute_spelling(int n) { + switch (n) { + case 0: + n++; + case 1: + #if defined(C2X) + // expected-warning@-2{{unannotated fall-through between switch labels}} expected-note@-2{{insert '[[fallthrough]];' to silence this warning}} expected-note@-2{{insert 'break;' to avoid fall-through}} + #else + // expected-warning@-4{{unannotated fall-through between switch labels}} expected-note@-4{{insert '__attribute__ ((fallthrough));' to silence this warning}} expected-note@-4{{insert 'break;' to avoid fall-through}} + #endif + n++; + __attribute__ ((fallthrough)); + case 2: + n++; + break; + } + return n; +} +// RUN: %clang_cc1 -fsyntax-only -std=gnu89 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=gnu99 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c99 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify -Wimplicit-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -std=c2x -DC2X -verify -Wimplicit-fallthrough %s + +int fallthrough_attribute_spelling(int n) { + switch (n) { + case 0: + n++; + case 1: + #if defined(C2X) + // expected-warning@-2{{unannotated fall-through between switch labels}} expected-note@-2{{insert '[[fallthrough]];' to silence this warning}} expected-note@-2{{insert 'break;' to avoid fall-through}} + #else + // expected-warning@-4{{unannotated fall-through between switch labels}} expected-note@-4{{insert '__attribute__ ((fallthrough));' to silence this warning}} expected-note@-4{{insert 'break;' to avoid fall-through}} + #endif + n++; + __attribute__ ((fallthrough)); + case 2: + n++; + break; + } + return n; +} \ No newline at end of file Index: test/SemaCXX/switch-implicit-fallthrough.cpp =================================================================== --- test/SemaCXX/switch-implicit-fallthrough.cpp +++ test/SemaCXX/switch-implicit-fallthrough.cpp @@ -329,3 +329,15 @@ } return n; } + +int fallthrough_attribute_spelling(int n) { + switch (n) { + case 0: + n++; + __attribute__ ((fallthrough)); + case 1: + n++; + break; + } + return n; +}