diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index da2e7ac47553e..76f5313cd8fa5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -366,6 +366,9 @@ Improvements to Clang's diagnostics been fixed and the Fix-It now only spans to the end of the ``:``. - Clang now underlines the parameter list of function declaration when emitting a note about the mismatch in the number of arguments. +- Clang now diagnoses unexpected tokens after a + ``#pragma clang|GCC diagnostic push|pop`` directive. + (`#13920: `_) Bug Fixes in This Version ------------------------- diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 0b892a3755a50..929e06d535713 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1291,16 +1291,26 @@ struct PragmaDiagnosticHandler : public PragmaHandler { IdentifierInfo *II = Tok.getIdentifierInfo(); PPCallbacks *Callbacks = PP.getPPCallbacks(); + // Get the next token, which is either an EOD or a string literal. We lex + // it now so that we can early return if the previous token was push or pop. + PP.LexUnexpandedToken(Tok); + if (II->isStr("pop")) { if (!PP.getDiagnostics().popMappings(DiagLoc)) PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); else if (Callbacks) Callbacks->PragmaDiagnosticPop(DiagLoc, Namespace); + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token); return; } else if (II->isStr("push")) { PP.getDiagnostics().pushMappings(DiagLoc); if (Callbacks) Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace); + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token); return; } @@ -1316,9 +1326,8 @@ struct PragmaDiagnosticHandler : public PragmaHandler { return; } - PP.LexUnexpandedToken(Tok); + // At this point, we expect a string literal. SourceLocation StringLoc = Tok.getLocation(); - std::string WarningName; if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic", /*AllowMacroExpansion=*/false)) diff --git a/clang/test/Preprocessor/pragma_diagnostic.c b/clang/test/Preprocessor/pragma_diagnostic.c index 75d2bbc7190f3..aeb888efc7cf2 100644 --- a/clang/test/Preprocessor/pragma_diagnostic.c +++ b/clang/test/Preprocessor/pragma_diagnostic.c @@ -34,6 +34,11 @@ // expected-warning@-2 {{unknown warning group '-Winvalid-name', ignored}} #endif +// From GH13920 +#pragma clang diagnostic push ignored "-Wdeprecated-declarations" // expected-warning {{unexpected token in pragma diagnostic}} +#pragma clang diagnostic pop ignored "-Wdeprecated-declarations" // expected-warning {{unexpected token in pragma diagnostic}} + + // Testing pragma clang diagnostic with -Weverything void ppo(void){} // First test that we do not diagnose on this.