Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -3544,12 +3544,14 @@ 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 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 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 Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -933,7 +933,8 @@ def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">, InGroup; 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< Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -475,8 +475,10 @@ 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(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; } Index: clang/test/Parser/fp-floatcontrol-syntax.cpp =================================================================== --- clang/test/Parser/fp-floatcontrol-syntax.cpp +++ clang/test/Parser/fp-floatcontrol-syntax.cpp @@ -5,15 +5,35 @@ 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; }