[clang] 7743882 - [MS compat] Handle #pragma fenv_access like #pragma STDC FENV_ACCESS (PR50694)
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 11 08:07:45 PDT 2021
Author: Hans Wennborg
Date: 2021-10-11T17:07:26+02:00
New Revision: 774388241e25529308c8bbac6012a20b62b82f29
URL: https://github.com/llvm/llvm-project/commit/774388241e25529308c8bbac6012a20b62b82f29
DIFF: https://github.com/llvm/llvm-project/commit/774388241e25529308c8bbac6012a20b62b82f29.diff
LOG: [MS compat] Handle #pragma fenv_access like #pragma STDC FENV_ACCESS (PR50694)
This adds support for the MSVC spelling of the pragma in -fms-extensions
mode.
Differential revision: https://reviews.llvm.org/D111440
Added:
clang/test/Parser/pragma-fenv_access-ms.c
Modified:
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParsePragma.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Parse/Parser.cpp
clang/test/CodeGen/pragma-fenv_access.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 8ae264caddcbf..f42c55be63f93 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1116,6 +1116,9 @@ def warn_pragma_expected_integer : Warning<
def warn_pragma_ms_struct : Warning<
"incorrect use of '#pragma ms_struct on|off' - ignored">,
InGroup<IgnoredPragmas>;
+def warn_pragma_ms_fenv_access : Warning<
+ "incorrect use of '#pragma fenv_access (on|off)' - ignored">,
+ InGroup<IgnoredPragmas>;
def warn_pragma_extra_tokens_at_eol : Warning<
"extra tokens at end of '#pragma %0' - ignored">,
InGroup<IgnoredPragmas>;
@@ -1181,9 +1184,6 @@ def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
// 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<UnknownPragmas>;
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 2b3dfedd020c0..0dd5936aa3e66 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -828,10 +828,11 @@ PRAGMA_ANNOTATION(pragma_redefine_extname)
// 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
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index de25760017b56..62c0a0d4c0a80 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -196,6 +196,7 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> MSRuntimeChecks;
std::unique_ptr<PragmaHandler> MSIntrinsic;
std::unique_ptr<PragmaHandler> MSOptimize;
+ std::unique_ptr<PragmaHandler> MSFenvAccess;
std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
std::unique_ptr<PragmaHandler> OptimizeHandler;
std::unique_ptr<PragmaHandler> LoopHintHandler;
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index c33605ef90251..27e8501278626 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -261,6 +261,68 @@ struct PragmaMSOptimizeHandler : public PragmaHandler {
Token &FirstToken) override;
};
+// "\#pragma fenv_access (on)".
+struct PragmaMSFenvAccessHandler : public PragmaHandler {
+ PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override {
+ StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
+ if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
+ PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
+ << PragmaName;
+ return;
+ }
+
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
+ << PragmaName;
+ return;
+ }
+ PP.Lex(Tok); // Consume the l_paren.
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
+ return;
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ tok::OnOffSwitch OOS;
+ 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_expected_rparen)
+ << PragmaName;
+ return;
+ }
+ PP.Lex(Tok); // Consume the r_paren.
+
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << PragmaName;
+ return;
+ }
+
+ MutableArrayRef<Token> Toks(
+ PP.getPreprocessorAllocator().Allocate<Token>(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<void*>(static_cast<uintptr_t>(OOS)));
+ PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
+ /*IsReinject=*/false);
+ }
+};
+
struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler(Sema &Actions)
: PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
@@ -389,6 +451,8 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSIntrinsic.get());
MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
PP.AddPragmaHandler(MSOptimize.get());
+ MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
+ PP.AddPragmaHandler(MSFenvAccess.get());
}
if (getLangOpts().CUDA) {
@@ -496,6 +560,8 @@ void Parser::resetPragmaHandlers() {
MSIntrinsic.reset();
PP.RemovePragmaHandler(MSOptimize.get());
MSOptimize.reset();
+ PP.RemovePragmaHandler(MSFenvAccess.get());
+ MSFenvAccess.reset();
}
if (getLangOpts().CUDA) {
@@ -701,7 +767,8 @@ void Parser::HandlePragmaFloatControl() {
}
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<tok::OnOffSwitch>(
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 9e259e15bd562..4d76dfe91052f 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -374,8 +374,11 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
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 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
HandlePragmaFP();
break;
case tok::annot_pragma_fenv_access:
+ case tok::annot_pragma_fenv_access_ms:
HandlePragmaFEnvAccess();
break;
case tok::annot_pragma_fenv_round:
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index c81dd03ffaaae..11113fa1a0603 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -785,6 +785,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
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:
diff --git a/clang/test/CodeGen/pragma-fenv_access.c b/clang/test/CodeGen/pragma-fenv_access.c
index fb7b8b2af61d5..0e2550bcc477d 100644
--- a/clang/test/CodeGen/pragma-fenv_access.c
+++ b/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 @@ float func_03(float x, float y) {
// 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)
diff --git a/clang/test/Parser/pragma-fenv_access-ms.c b/clang/test/Parser/pragma-fenv_access-ms.c
new file mode 100644
index 0000000000000..d179dfeb8780c
--- /dev/null
+++ b/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{{missing '(' after '#pragma fenv_access'}}
+#pragma fenv_access foo // expected-warning{{missing '(' after '#pragma fenv_access'}}
+#pragma fenv_access on // expected-warning{{missing '(' after '#pragma fenv_access'}}
+#pragma fenv_access ( // expected-warning{{incorrect use of '#pragma fenv_access}}
+#pragma fenv_access (on // expected-warning{{missing ')' after '#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}}
+}
More information about the cfe-commits
mailing list