Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -47,6 +47,9 @@ "inside instance variable list|" "after member function definition}0">, InGroup; +def warn_extra_semi : Warning< + "extra ';' outside of a function">, + InGroup, DefaultIgnore; def ext_extra_semi_cxx11 : Extension< "extra ';' outside of a function is a C++11 extension">, InGroup; Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -191,12 +191,20 @@ // C++11 allows extra semicolons at namespace scope, but not in any of the // other contexts. if (Kind == OutsideFunction && getLangOpts().CPlusPlus) { + unsigned DiagID; + if (getLangOpts().CPlusPlus11) - Diag(StartLoc, diag::warn_cxx98_compat_top_level_semi) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + DiagID = diag::warn_cxx98_compat_top_level_semi; else - Diag(StartLoc, diag::ext_extra_semi_cxx11) - << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + DiagID = diag::ext_extra_semi_cxx11; + + // Prefer the pedantic compatibility warning over the generic, + // non-extension, user-requested "extra semi" warning. + if (Diags.isIgnored(DiagID, EndLoc)) + DiagID = diag::warn_extra_semi; + + Diag(StartLoc, DiagID) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); return; } Index: test/Parser/cxx-extra-semi.cpp =================================================================== --- test/Parser/cxx-extra-semi.cpp +++ test/Parser/cxx-extra-semi.cpp @@ -38,4 +38,7 @@ #if __cplusplus < 201103L // expected-warning@-3{{extra ';' outside of a function is a C++11 extension}} // expected-warning@-3{{extra ';' outside of a function is a C++11 extension}} +#elif !defined(PEDANTIC) +// expected-warning@-6{{extra ';' outside of a function}} +// expected-warning@-6{{extra ';' outside of a function}} #endif Index: test/SemaCXX/extra-semi.cpp =================================================================== --- /dev/null +++ test/SemaCXX/extra-semi.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -verify -std=c++98 -Wextra-semi %s +// RUN: %clang_cc1 -verify -std=c++03 -Wextra-semi %s +// RUN: %clang_cc1 -verify -std=c++11 -Wextra-semi %s +// RUN: %clang_cc1 -verify -std=c++17 -Wextra-semi %s +// RUN: %clang_cc1 -verify -std=c++2a -Wextra-semi %s +// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat %s +// RUN: %clang_cc1 -verify -Weverything -Wno-c++98-compat-pedantic %s + +// Last two RUN lines check that -Wextra-semi, which was enabled by +// -Weverything will still be issued even though -Wc++98-compat contains +// diag::warn_cxx98_compat_top_level_semi, which would be silenced by -Wno-. + +void F(); + +void F() {} +; // expected-warning {{extra ';' outside of a function}} + +namespace ns { +class C { + void F() const; +}; +} +; // expected-warning {{extra ';' outside of a function}} + +void ns::C::F() const {} +; // expected-warning {{extra ';' outside of a function}}