Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1110,6 +1110,9 @@ def warn_pragma_ms_struct : Warning< "incorrect use of '#pragma ms_struct on|off' - ignored">, InGroup; +def warn_pragma_ms_fenv_access : Warning< + "incorrect use of '#pragma fenv_access (on|off)' - ignored">, + InGroup; def warn_pragma_extra_tokens_at_eol : Warning< "extra tokens at end of '#pragma %0' - ignored">, InGroup; @@ -1175,9 +1178,6 @@ // The C standard 7.6.1p2 says "The [FENV_ACCESS] pragma shall occur either // outside external declarations or preceding all explicit declarations and // statements inside a compound statement. -def err_pragma_stdc_fenv_access_scope : Error< - "'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of" - " a compound statement">; def warn_stdc_fenv_round_not_supported : Warning<"pragma STDC FENV_ROUND is not supported">, InGroup; Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ clang/include/clang/Basic/TokenKinds.def @@ -828,10 +828,11 @@ // handles them. PRAGMA_ANNOTATION(pragma_fp_contract) -// Annotation for #pragma STDC FENV_ACCESS +// Annotations for #pragma STDC FENV_ACCESS and #pragma fenv_access (MS compat) // The lexer produces these so that they only take effect when the parser // handles them. PRAGMA_ANNOTATION(pragma_fenv_access) +PRAGMA_ANNOTATION(pragma_fenv_access_ms) // Annotation for #pragma STDC FENV_ROUND // The lexer produces these so that they only take effect when the parser Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -196,6 +196,7 @@ std::unique_ptr MSRuntimeChecks; std::unique_ptr MSIntrinsic; std::unique_ptr MSOptimize; + std::unique_ptr MSFenvAccess; std::unique_ptr CUDAForceHostDeviceHandler; std::unique_ptr OptimizeHandler; std::unique_ptr LoopHintHandler; Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -261,6 +261,66 @@ Token &FirstToken) override; }; +// "\#pragma fenv_access (on)". +struct PragmaMSFenvAccessHandler : public PragmaHandler { + PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override { + Token PragmaName = FirstToken; + if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { + PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored) + << PragmaName.getIdentifierInfo()->getName(); + return; + } + + tok::OnOffSwitch OOS; + Token Tok; + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access); + return; + } + PP.Lex(Tok); // Eat the l_paren + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("on")) { + OOS = tok::OOS_ON; + PP.Lex(Tok); + } else if (II->isStr("off")) { + OOS = tok::OOS_OFF; + PP.Lex(Tok); + } else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access); + return; + } + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access); + return; + } + PP.Lex(Tok); // Eat the r_paren + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "fenv_access"; + return; + } + + MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1), + 1); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_fenv_access_ms); + Toks[0].setLocation(FirstToken.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast( + static_cast(OOS))); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, + /*IsReinject=*/false); + } +}; + struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler { PragmaForceCUDAHostDeviceHandler(Sema &Actions) : PragmaHandler("force_cuda_host_device"), Actions(Actions) {} @@ -389,6 +449,8 @@ PP.AddPragmaHandler(MSIntrinsic.get()); MSOptimize = std::make_unique(); PP.AddPragmaHandler(MSOptimize.get()); + MSFenvAccess = std::make_unique(); + PP.AddPragmaHandler(MSFenvAccess.get()); } if (getLangOpts().CUDA) { @@ -496,6 +558,8 @@ MSIntrinsic.reset(); PP.RemovePragmaHandler(MSOptimize.get()); MSOptimize.reset(); + PP.RemovePragmaHandler(MSFenvAccess.get()); + MSFenvAccess.reset(); } if (getLangOpts().CUDA) { @@ -701,7 +765,8 @@ } void Parser::HandlePragmaFEnvAccess() { - assert(Tok.is(tok::annot_pragma_fenv_access)); + assert(Tok.is(tok::annot_pragma_fenv_access) || + Tok.is(tok::annot_pragma_fenv_access_ms)); tok::OnOffSwitch OOS = static_cast( reinterpret_cast(Tok.getAnnotationValue())); Index: clang/lib/Parse/ParseStmt.cpp =================================================================== --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -374,8 +374,11 @@ return StmtError(); case tok::annot_pragma_fenv_access: + case tok::annot_pragma_fenv_access_ms: ProhibitAttributes(Attrs); - Diag(Tok, diag::err_pragma_stdc_fenv_access_scope); + Diag(Tok, diag::err_pragma_file_or_compound_scope) << + (Kind == tok::annot_pragma_fenv_access ? "STDC FENV_ACCESS" + : "fenv_access"); ConsumeAnnotationToken(); return StmtEmpty(); @@ -955,6 +958,7 @@ HandlePragmaFP(); break; case tok::annot_pragma_fenv_access: + case tok::annot_pragma_fenv_access_ms: HandlePragmaFEnvAccess(); break; case tok::annot_pragma_fenv_round: Index: clang/lib/Parse/Parser.cpp =================================================================== --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -785,6 +785,7 @@ HandlePragmaFPContract(); return nullptr; case tok::annot_pragma_fenv_access: + case tok::annot_pragma_fenv_access_ms: HandlePragmaFEnvAccess(); return nullptr; case tok::annot_pragma_fenv_round: Index: clang/test/CodeGen/pragma-fenv_access.c =================================================================== --- clang/test/CodeGen/pragma-fenv_access.c +++ clang/test/CodeGen/pragma-fenv_access.c @@ -1,6 +1,11 @@ // RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - -fms-extensions -DMS | FileCheck %s +#ifdef MS +#pragma fenv_access (on) +#else #pragma STDC FENV_ACCESS ON +#endif float func_01(float x, float y) { return x + y; @@ -25,7 +30,11 @@ // CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict") +#ifdef MS +#pragma fenv_access (off) +#else #pragma STDC FENV_ACCESS OFF +#endif float func_04(float x, float y) { #pragma float_control(except, off) Index: clang/test/Parser/pragma-fenv_access-ms.c =================================================================== --- /dev/null +++ clang/test/Parser/pragma-fenv_access-ms.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -fsyntax-only -verify %s + +#pragma fenv_access (on) +#pragma fenv_access (off) + +#pragma fenv_access // expected-warning{{incorrect use of '#pragma fenv_access}} +#pragma fenv_access foo // expected-warning{{incorrect use of '#pragma fenv_access}} +#pragma fenv_access on // expected-warning{{incorrect use of '#pragma fenv_access}} +#pragma fenv_access ( // expected-warning{{incorrect use of '#pragma fenv_access}} +#pragma fenv_access (on // expected-warning{{incorrect use of '#pragma fenv_access}} +#pragma fenv_access (on) foo // expected-warning{{extra tokens at end of '#pragma fenv_access'}} + +void f() { + (void)0; + #pragma fenv_access (on) // expected-error{{'#pragma fenv_access' can only appear at file scope or at the start of a compound statement}} +}