Index: include/clang/Basic/DiagnosticLexKinds.td =================================================================== --- include/clang/Basic/DiagnosticLexKinds.td +++ include/clang/Basic/DiagnosticLexKinds.td @@ -505,8 +505,6 @@ def err_pragma_message : Error<"%0">; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup, DefaultIgnore; -def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, - InGroup; def ext_on_off_switch_syntax : ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">, InGroup; Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -973,6 +973,9 @@ def err_pragma_fp_contract_scope : Error< "'#pragma fp_contract' can only appear at file scope or at the start of a " "compound statement">; +// - #pragma stdc unknown +def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, + InGroup; // - #pragma comment def err_pragma_comment_malformed : Error< "pragma comment requires parenthesized identifier and optional string">; Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -185,6 +185,7 @@ std::unique_ptr UnrollHintHandler; std::unique_ptr NoUnrollHintHandler; std::unique_ptr FPHandler; + std::unique_ptr STDCUnknownHandler; std::unique_ptr AttributePragmaHandler; std::unique_ptr CommentSemaHandler; Index: lib/Frontend/PrintPreprocessedOutput.cpp =================================================================== --- lib/Frontend/PrintPreprocessedOutput.cpp +++ lib/Frontend/PrintPreprocessedOutput.cpp @@ -851,9 +851,14 @@ "#pragma clang", Callbacks, /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + std::unique_ptr STDCHandler(new UnknownPragmaHandler( + "#pragma STDC", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + PP.AddPragmaHandler(MicrosoftExtHandler.get()); PP.AddPragmaHandler("GCC", GCCHandler.get()); PP.AddPragmaHandler("clang", ClangHandler.get()); + PP.AddPragmaHandler("STDC", STDCHandler.get()); // The tokens after pragma omp need to be expanded. // @@ -897,5 +902,6 @@ PP.RemovePragmaHandler(MicrosoftExtHandler.get()); PP.RemovePragmaHandler("GCC", GCCHandler.get()); PP.RemovePragmaHandler("clang", ClangHandler.get()); + PP.RemovePragmaHandler("STDC", STDCHandler.get()); PP.RemovePragmaHandler("omp", OpenMPHandler.get()); } Index: lib/Lex/Pragma.cpp =================================================================== --- lib/Lex/Pragma.cpp +++ lib/Lex/Pragma.cpp @@ -1628,17 +1628,6 @@ } }; -/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". -struct PragmaSTDC_UnknownHandler : public PragmaHandler { - PragmaSTDC_UnknownHandler() = default; - - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &UnknownTok) override { - // C99 6.10.6p2, unknown forms are not allowed. - PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); - } -}; - /// PragmaARCCFCodeAuditedHandler - /// \#pragma clang arc_cf_code_audited begin/end struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { @@ -1815,9 +1804,9 @@ ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); ModuleHandler->AddPragma(new PragmaModuleLoadHandler()); + // #pragma STDC AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); - AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); // MS extensions. if (LangOpts.MicrosoftExt) { @@ -1843,17 +1832,5 @@ // in Preprocessor::RegisterBuiltinPragmas(). AddPragmaHandler("GCC", new EmptyPragmaHandler()); AddPragmaHandler("clang", new EmptyPragmaHandler()); - if (PragmaHandler *NS = PragmaHandlers->FindHandler("STDC")) { - // Preprocessor::RegisterBuiltinPragmas() already registers - // PragmaSTDC_UnknownHandler as the empty handler, so remove it first, - // otherwise there will be an assert about a duplicate handler. - PragmaNamespace *STDCNamespace = NS->getIfNamespace(); - assert(STDCNamespace && - "Invalid namespace, registered as a regular pragma handler!"); - if (PragmaHandler *Existing = STDCNamespace->FindHandler("", false)) { - RemovePragmaHandler("STDC", Existing); - delete Existing; - } - } AddPragmaHandler("STDC", new EmptyPragmaHandler()); } Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -95,6 +95,17 @@ Token &FirstToken) override; }; +/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". +struct PragmaSTDC_UnknownHandler : public PragmaHandler { + PragmaSTDC_UnknownHandler() = default; + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) override { + // C99 6.10.6p2, unknown forms are not allowed. + PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); + } +}; + struct PragmaFPHandler : public PragmaHandler { PragmaFPHandler() : PragmaHandler("fp") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -233,6 +244,9 @@ FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); + STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler()); + PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); + PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); PP.AddPragmaHandler("clang", PCSectionHandler.get()); @@ -371,6 +385,9 @@ PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); + PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get()); + STDCUnknownHandler.reset(); + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); OptimizeHandler.reset(); Index: test/Preprocessor/pragma_unknown.c =================================================================== --- test/Preprocessor/pragma_unknown.c +++ test/Preprocessor/pragma_unknown.c @@ -1,14 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -Wunknown-pragmas -verify %s -// RUN: %clang_cc1 -E %s | FileCheck --strict-whitespace %s +// RUN: %clang_cc1 -E %s 2>&1 | FileCheck --strict-whitespace %s // GCC doesn't expand macro args for unrecognized pragmas. #define bar xX #pragma foo bar // expected-warning {{unknown pragma ignored}} +// CHECK-NOT: unknown pragma in STDC namespace // CHECK: {{^}}#pragma foo bar{{$}} #pragma STDC FP_CONTRACT ON #pragma STDC FP_CONTRACT OFF #pragma STDC FP_CONTRACT DEFAULT +// CHECK: {{^}}#pragma STDC FP_CONTRACT ON{{$}} +// CHECK: {{^}}#pragma STDC FP_CONTRACT OFF{{$}} +// CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}} #pragma STDC FP_CONTRACT IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} #pragma STDC FENV_ACCESS ON // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}