mibintc created this revision. mibintc added reviewers: rjmccall, erichkeane. Herald added a project: clang. Herald added a subscriber: cfe-commits.
I got a bug report from Intel that https://reviews.llvm.org/D72841 was causing a crash on Windows in vs2017 <numeric> header in /std:c++17 mode, because #pragma float_control is used in a namespace. This patch allows float_control to be in a namespace. I checked the Microsoft compiler to see if the namespace caused the effectiveness of the pragma to be scoped (i.e. a pragma in the namespace would not be effective after the namespace closed) and the pragma is still effective after the namespace. I added the test case that I used for the investigation to the LIT tests. I used this compile line and checked the assembly. cl -c test.cpp -Fatest.asm /arch:AVX2 -O2 ; when the pragma is in effect the div instruction is not eliminated. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D79631 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaAttr.cpp clang/test/CodeGen/fp-floatcontrol-pragma.cpp clang/test/Parser/fp-floatcontrol-syntax.cpp Index: clang/test/Parser/fp-floatcontrol-syntax.cpp =================================================================== --- clang/test/Parser/fp-floatcontrol-syntax.cpp +++ clang/test/Parser/fp-floatcontrol-syntax.cpp @@ -10,10 +10,10 @@ #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}} -#pragma float_control(pop) // expected-error {{can only appear at file scope}} -#pragma float_control(precise, on, push) // expected-error {{can only appear at file scope}} -#pragma float_control(except, on, push) // expected-error {{can only appear at file scope}} +#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}} #pragma float_control(except, on, push, junk) // expected-error {{float_control is malformed}} return; } Index: clang/test/CodeGen/fp-floatcontrol-pragma.cpp =================================================================== --- clang/test/CodeGen/fp-floatcontrol-pragma.cpp +++ clang/test/CodeGen/fp-floatcontrol-pragma.cpp @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s @@ -59,3 +60,38 @@ z = z * z; //CHECK: = fmul float } + +#if EXCEPT +namespace ns { +// Check that pragma float_control can appear in namespace. +#pragma float_control(except, on, push) +float exc_on(double x, float zero) { +// CHECK-NS: define {{.*}}exc_on{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} + } catch (...) {} + return zero; +} +} + +// Check pragma is still effective after namespace closes +float exc_still_on(double x, float zero) { +// CHECK-NS: define {{.*}}exc_still_on{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} + } catch (...) {} + return zero; +} + +#pragma float_control(pop) +float exc_off(double x, float zero) { +// CHECK-NS: define {{.*}}exc_off{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: fdiv contract double + } catch (...) {} + return zero; +} +#endif // EXCEPT Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -413,8 +413,8 @@ auto NewValue = FpPragmaStack.CurrentValue; FPOptions NewFPFeatures(NewValue); if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) && - !CurContext->isTranslationUnit()) { - // Push and pop can only occur at file scope. + !(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) { + // Push and pop can only occur at file or namespace scope. Diag(Loc, diag::err_pragma_fc_pp_scope); return; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -860,7 +860,7 @@ 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">; + "'#pragma float_control push/pop' can only appear at file scope or namespace scope">; 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/test/Parser/fp-floatcontrol-syntax.cpp =================================================================== --- clang/test/Parser/fp-floatcontrol-syntax.cpp +++ clang/test/Parser/fp-floatcontrol-syntax.cpp @@ -10,10 +10,10 @@ #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}} -#pragma float_control(pop) // expected-error {{can only appear at file scope}} -#pragma float_control(precise, on, push) // expected-error {{can only appear at file scope}} -#pragma float_control(except, on, push) // expected-error {{can only appear at file scope}} +#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}} #pragma float_control(except, on, push, junk) // expected-error {{float_control is malformed}} return; } Index: clang/test/CodeGen/fp-floatcontrol-pragma.cpp =================================================================== --- clang/test/CodeGen/fp-floatcontrol-pragma.cpp +++ clang/test/CodeGen/fp-floatcontrol-pragma.cpp @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s @@ -59,3 +60,38 @@ z = z * z; //CHECK: = fmul float } + +#if EXCEPT +namespace ns { +// Check that pragma float_control can appear in namespace. +#pragma float_control(except, on, push) +float exc_on(double x, float zero) { +// CHECK-NS: define {{.*}}exc_on{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} + } catch (...) {} + return zero; +} +} + +// Check pragma is still effective after namespace closes +float exc_still_on(double x, float zero) { +// CHECK-NS: define {{.*}}exc_still_on{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}} + } catch (...) {} + return zero; +} + +#pragma float_control(pop) +float exc_off(double x, float zero) { +// CHECK-NS: define {{.*}}exc_off{{.*}} + {} try { + x = 1.0 / zero; /* division by zero, the result unused */ +//CHECK-NS: fdiv contract double + } catch (...) {} + return zero; +} +#endif // EXCEPT Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -413,8 +413,8 @@ auto NewValue = FpPragmaStack.CurrentValue; FPOptions NewFPFeatures(NewValue); if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) && - !CurContext->isTranslationUnit()) { - // Push and pop can only occur at file scope. + !(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) { + // Push and pop can only occur at file or namespace scope. Diag(Loc, diag::err_pragma_fc_pp_scope); return; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -860,7 +860,7 @@ 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">; + "'#pragma float_control push/pop' can only appear at file scope or namespace scope">; 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<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits