[clang] b0ef3d8 - Allow #pragma float_control(push|pop) within a language linkage specification

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 28 04:38:44 PDT 2021


Author: Aaron Ballman
Date: 2021-07-28T07:37:56-04:00
New Revision: b0ef3d8f666fa6008abb09340b73d9340d442569

URL: https://github.com/llvm/llvm-project/commit/b0ef3d8f666fa6008abb09340b73d9340d442569
DIFF: https://github.com/llvm/llvm-project/commit/b0ef3d8f666fa6008abb09340b73d9340d442569.diff

LOG: Allow #pragma float_control(push|pop) within a language linkage specification

Currently, we prohibit this pragma from appearing within a language
linkage specification, but this is useful functionality that is
supported by MSVC (which is where we inherited this feature from).
This patch allows you to use the pragma within an extern "C" {} (etc)
block.

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaAttr.cpp
    clang/test/Parser/fp-floatcontrol-syntax.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index f14f986c646a4..8090aedb573bf 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3544,12 +3544,14 @@ A ``#pragma clang fp`` pragma may contain any number of options:
 
 The ``#pragma float_control`` pragma allows precise floating-point
 semantics and floating-point exception behavior to be specified
-for a section of the source code. This pragma can only appear at file scope or
-at the start of a compound statement (excluding comments). When using within a
-compound statement, the pragma is active within the scope of the compound
-statement.  This pragma is modeled after a Microsoft pragma with the
-same spelling and syntax.  For pragmas specified at file scope, a stack
-is supported so that the ``pragma float_control`` settings can be pushed or popped.
+for a section of the source code. This pragma can only appear at file or
+namespace scope, within a language linkage specification or at the start of a
+compound statement (excluding comments). When used within a compound statement,
+the pragma is active within the scope of the compound statement.  This pragma
+is modeled after a Microsoft pragma with the same spelling and syntax.  For
+pragmas specified at file or namespace scope, or within a language linkage
+specification, a stack is supported so that the ``pragma float_control``
+settings can be pushed or popped.
 
 When ``pragma float_control(precise, on)`` is enabled, the section of code
 governed by the pragma uses precise floating point semantics, effectively

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 108f1796415c8..00b443b45f132 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -933,7 +933,8 @@ def warn_pragma_pack_pop_identifier_and_alignment : Warning<
 def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
   InGroup<IgnoredPragmas>;
 def err_pragma_fc_pp_scope : Error<
-  "'#pragma float_control push/pop' can only appear at file scope or namespace scope">;
+  "'#pragma float_control push/pop' can only appear at file or namespace scope "
+  "or within a language linkage specification">;
 def err_pragma_fc_noprecise_requires_nofenv : Error<
   "'#pragma float_control(precise, off)' is illegal when fenv_access is enabled">;
 def err_pragma_fc_except_requires_precise : Error<

diff  --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index fe8f02f023685..4a209166c4ff0 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -475,8 +475,10 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
                                    PragmaFloatControlKind Value) {
   FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
   if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
-      !(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) {
-    // Push and pop can only occur at file or namespace scope.
+      !(CurContext->isTranslationUnit()) && !CurContext->isNamespace() &&
+      !isa<LinkageSpecDecl>(CurContext)) {
+    // Push and pop can only occur at file or namespace scope, or within a
+    // language linkage declaration.
     Diag(Loc, diag::err_pragma_fc_pp_scope);
     return;
   }

diff  --git a/clang/test/Parser/fp-floatcontrol-syntax.cpp b/clang/test/Parser/fp-floatcontrol-syntax.cpp
index 570821fe7468a..7f5a665252c0e 100644
--- a/clang/test/Parser/fp-floatcontrol-syntax.cpp
+++ b/clang/test/Parser/fp-floatcontrol-syntax.cpp
@@ -5,15 +5,35 @@ float function_scope(float a) {
   return a;
 }
 
+// Ok, at namespace scope.
+namespace foo {
+#pragma float_control(push)
+#pragma float_control(pop)
+}
+
+// Ok, within a language linkage specification.
+extern "C" {
+#pragma float_control(push)
+#pragma float_control(pop)
+}
+
+// Same.
+extern "C++" {
+#pragma float_control(push)
+#pragma float_control(pop)
+}
+
 #ifdef CHECK_ERROR
+// Ok at file scope.
 #pragma float_control(push)
 #pragma float_control(pop)
 #pragma float_control(precise, on, push)
 void check_stack() {
-#pragma float_control(push)                   // expected-error {{can only appear at file scope or namespace scope}}
-#pragma float_control(pop)                    // expected-error {{can only appear at file scope or namespace scope}}
-#pragma float_control(precise, on, push)      // expected-error {{can only appear at file scope or namespace scope}}
-#pragma float_control(except, on, push)       // expected-error {{can only appear at file scope or namespace scope}}
+  // Not okay within a function declaration.
+#pragma float_control(push)                   // expected-error {{can only appear at file or namespace scope or within a language linkage specification}}
+#pragma float_control(pop)                    // expected-error {{can only appear at file or namespace scope or within a language linkage specification}}
+#pragma float_control(precise, on, push)      // expected-error {{can only appear at file or namespace scope or within a language linkage specification}}
+#pragma float_control(except, on, push)       // expected-error {{can only appear at file or namespace scope or within a language linkage specification}}
 #pragma float_control(except, on, push, junk) // expected-error {{float_control is malformed}}
   return;
 }


        


More information about the cfe-commits mailing list