zahiraam updated this revision to Diff 508176.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D146148/new/
https://reviews.llvm.org/D146148
Files:
clang/docs/LanguageExtensions.rst
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/Sema/Inputs/math.h
clang/test/Sema/abi-check-1.cpp
clang/test/Sema/abi-check-2.cpp
clang/test/Sema/abi-check-3.cpp
clang/test/Sema/attr-only-in-default-eval.cpp
Index: clang/test/Sema/attr-only-in-default-eval.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-only-in-default-eval.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef float float_t [[clang::available_only_in_default_eval_method]];
+using double_t __attribute__((available_only_in_default_eval_method)) = double;
+
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+class __attribute__((available_only_in_default_eval_method)) C1 {
+};
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+class [[clang::available_only_in_default_eval_method]] C2 {
+};
+
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+struct [[clang::available_only_in_default_eval_method]] S1;
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+struct __attribute__((available_only_in_default_eval_method)) S2;
+
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+void __attribute__((available_only_in_default_eval_method)) foo();
+// expected-error@+1{{'available_only_in_default_eval_method' attribute cannot be applied to types}}
+void [[clang::available_only_in_default_eval_method]] goo();
+// expected-error@+1{{'available_only_in_default_eval_method' attribute cannot be applied to types}}
+void bar() [[clang::available_only_in_default_eval_method]];
+// expected-error@+1{{'available_only_in_default_eval_method' attribute only applies to typedefs}}
+void barz() __attribute__((available_only_in_default_eval_method));
+
Index: clang/test/Sema/abi-check-3.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/abi-check-3.cpp
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=source -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=double -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+// RUN: %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=extended -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-EXT %s
+
+#include <math.h>
+
+float foo1() {
+#pragma clang fp eval_method(extended)
+ float a;
+ double b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ return a - b;
+}
+
+float foo2() {
+#pragma clang fp eval_method(extended)
+ float_t a;
+ double_t b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-EXT: alloca x86_fp80
+ // CHECK-EXT: alloca x86_fp80
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+void foo3() {
+#pragma clang fp eval_method(extended)
+ char buff[sizeof(float_t)];
+ char bufd[sizeof(double_t)];
+ // CHECK: alloca [4 x i8]
+ // CHECK: alloca [8 x i8]
+ // CHECK-DBL: alloca [8 x i8]
+ // CHECK-DBL: alloca [8 x i8]
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ buff[1] = bufd[2];
+}
+
+float foo4() {
+#pragma clang fp eval_method(extended)
+ typedef float_t FT;
+ typedef double_t DT;
+ FT a;
+ DT b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-EXT: alloca x86_fp80
+ // CHECK-EXT: alloca x86_fp80
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+int foo5() {
+#pragma clang fp eval_method(extended)
+ int t = _Generic( 1.0L, float_t:1, default:0);
+ int v = _Generic( 1.0L, double_t:1, default:0);
+ // CHECK: alloca i32
+ // CHECK: alloca i32
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return t;
+}
+
+void foo6() {
+#pragma clang fp eval_method(extended)
+ auto resf = [](float_t f) { return f; };
+ auto resd = [](double_t g) { return g; };
+ // CHECK: alloca %class.anon
+ // CHECK: alloca %class.anon
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo7() {
+#pragma clang fp eval_method(extended)
+ float f = (float_t)1;
+ double d = (double_t)2;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo8() {
+#pragma clang fp eval_method(extended)
+ using Ft = float_t;
+ using Dt = double_t;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-EXT: alloca x86_fp80
+ // CHECK-EXT: alloca x86_fp80
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ Ft a;
+ Dt b;
+}
+
+void foo9() {
+#pragma clang fp eval_method(extended)
+ float c1 = (float_t)12;
+ double c2 = (double_t)13;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+float foo10() {
+#pragma clang fp eval_method(extended)
+ extern float_t f;
+ extern double_t g;
+ // CHECK: load double
+ // CHECK-EXT: load x86_fp80
+ // CHECK-EXT: load x86_fp80
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return f-g;
+}
Index: clang/test/Sema/abi-check-2.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/abi-check-2.cpp
@@ -0,0 +1,131 @@
+// RUN: %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=source -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+// RUN: %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=double -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-DBL %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=extended -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+#include <math.h>
+
+float foo1() {
+#pragma clang fp eval_method(double)
+ float a;
+ double b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ return a - b;
+}
+
+float foo2() {
+#pragma clang fp eval_method(double)
+ float_t a;
+ double_t b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-DBL: alloca double
+ // CHECK-DBL: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+void foo3() {
+#pragma clang fp eval_method(double)
+ char buff[sizeof(float_t)];
+ char bufd[sizeof(double_t)];
+ // CHECK: alloca [4 x i8]
+ // CHECK: alloca [8 x i8]
+ // CHECK-DBL: alloca [8 x i8]
+ // CHECK-DBL: alloca [8 x i8]
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ buff[1] = bufd[2];
+}
+
+float foo4() {
+#pragma clang fp eval_method(double)
+ typedef float_t FT;
+ typedef double_t DT;
+ FT a;
+ DT b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-DBL: alloca double
+ // CHECK-DBL: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+int foo5() {
+#pragma clang fp eval_method(double)
+ int t = _Generic( 1.0L, float_t:1, default:0);
+ int v = _Generic( 1.0L, double_t:1, default:0);
+ // CHECK: alloca i32
+ // CHECK: alloca i32
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return t;
+}
+
+void foo6() {
+#pragma clang fp eval_method(double)
+ auto resf = [](float_t f) { return f; };
+ auto resd = [](double_t g) { return g; };
+ // CHECK: alloca %class.anon
+ // CHECK: alloca %class.anon
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo7() {
+#pragma clang fp eval_method(double)
+ float f = (float_t)1;
+ double d = (double_t)2;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo8() {
+#pragma clang fp eval_method(double)
+ using Ft = float_t;
+ using Dt = double_t;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // CHECK-DBL: alloca double
+ // CHECK-DBL: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ Ft a;
+ Dt b;
+}
+
+void foo9() {
+#pragma clang fp eval_method(double)
+ float c1 = (float_t)12;
+ double c2 = (double_t)13;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+float foo10() {
+#pragma clang fp eval_method(double)
+ extern float_t f;
+ extern double_t g;
+ // CHECK: load double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return f-g;
+}
Index: clang/test/Sema/abi-check-1.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/abi-check-1.cpp
@@ -0,0 +1,121 @@
+// RUN: %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+
+// RUN: %clang_cc1 -isystem %S/Inputs -ffp-eval-method=source \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=double -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+// RUN: not %clang_cc1 -isystem %S/Inputs -triple x86_64-linux-gnu \
+// RUN: -ffp-eval-method=extended -emit-obj -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=ERROR %s
+
+#include <math.h>
+
+float foo1() {
+#pragma clang fp eval_method(source)
+ float a;
+ double b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ return a - b;
+}
+
+float foo2() {
+#pragma clang fp eval_method(source)
+ float_t a;
+ double_t b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+void foo3() {
+#pragma clang fp eval_method(source)
+ char buff[sizeof(float_t)];
+ char bufd[sizeof(double_t)];
+ // CHECK: alloca [4 x i8]
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ buff[1] = bufd[2];
+}
+
+float foo4() {
+#pragma clang fp eval_method(source)
+ typedef float_t FT;
+ typedef double_t DT;
+ FT a;
+ DT b;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return a - b;
+}
+
+int foo5() {
+#pragma clang fp eval_method(source)
+ int t = _Generic( 1.0L, float_t:1, default:0);
+ int v = _Generic( 1.0L, double_t:1, default:0);
+ // CHECK: alloca i32
+ // CHECK: alloca i32
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return t;
+}
+
+void foo6() {
+#pragma clang fp eval_method(source)
+ auto resf = [](float_t f) { return f; };
+ auto resd = [](double_t g) { return g; };
+ // CHECK: alloca %class.anon
+ // CHECK: alloca %class.anon
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo7() {
+#pragma clang fp eval_method(source)
+ float f = (float_t)1;
+ double d = (double_t)2;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+void foo8() {
+#pragma clang fp eval_method(source)
+ using Ft = float_t;
+ using Dt = double_t;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ Ft a;
+ Dt b;
+}
+
+void foo9() {
+#pragma clang fp eval_method(source)
+ float c1 = (float_t)12;
+ double c2 = (double_t)13;
+ // CHECK: alloca float
+ // CHECK: alloca double
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+}
+
+float foo10() {
+#pragma clang fp eval_method(source)
+ extern float_t f;
+ extern double_t g;
+ // CHECK: load float
+ // ERROR: error: cannot use type 'float_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ // ERROR: error: cannot use type 'double_t' within '#pragma clang fp eval_method'; type is set according to the default eval method for the translation unit
+ return f-g;
+}
Index: clang/test/Sema/Inputs/math.h
===================================================================
--- /dev/null
+++ clang/test/Sema/Inputs/math.h
@@ -0,0 +1,43 @@
+#ifdef __FLT_EVAL_METHOD__
+#if __FLT_EVAL_METHOD__ == -1
+#define __GLIBC_FLT_EVAL_METHOD 2
+#else
+#define __GLIBC_FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#endif
+#elif defined __x86_64__
+#define __GLIBC_FLT_EVAL_METHOD 0
+#else
+#define __GLIBC_FLT_EVAL_METHOD 2
+#endif
+
+# if __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16
+typedef float float_t [[clang::available_only_in_default_eval_method]];
+using double_t [[clang::available_only_in_default_eval_method]] = double;
+# elif __GLIBC_FLT_EVAL_METHOD == 1
+typedef double float_t [[clang::available_only_in_default_eval_method]];
+typedef double double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 2
+typedef long double float_t [[clang::available_only_in_default_eval_method]];
+typedef long double double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 32
+typedef _Float32 float_t [[clang::available_only_in_default_eval_method]];
+typedef double double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 33
+typedef _Float32x float_t [[clang::available_only_in_default_eval_method]];
+typedef _Float32x double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 64
+using float_t [[clang::available_only_in_default_eval_method]] = _Float64
+typedef _Float64 double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 65
+typedef _Float64x float_t [[clang::available_only_in_default_eval_method]];
+typedef _Float64x double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 128
+typedef _Float128 float_t [[clang::available_only_in_default_eval_method]];
+typedef _Float128 double_t [[clang::available_only_in_default_eval_method]];
+# elif __GLIBC_FLT_EVAL_METHOD == 129
+typedef _Float128x float_t [[clang::available_only_in_default_eval_method]];
+using double_t __attribute__((available_only_in_default_eval_method)) = _Float128x;
+# else
+# error "Unknown __GLIBC_FLT_EVAL_METHOD"
+# endif
+
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -375,6 +375,16 @@
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
+ if (D->hasAttr<AvailableOnlyInDefaultEvalMethodAttr>()) {
+ if (getLangOpts().getFPEvalMethod() !=
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine &&
+ PP.getLastFPEvalPragmaLocation().isValid() &&
+ PP.getCurrentFPEvalMethod() != getLangOpts().getFPEvalMethod())
+ Diag(D->getLocation(),
+ diag::err_type_available_only_in_default_eval_method)
+ << D->getName();
+ }
+
if (auto *VD = dyn_cast<ValueDecl>(D))
checkTypeSupport(VD->getType(), Loc, VD);
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8255,6 +8255,12 @@
D->addAttr(FunctionReturnThunksAttr::Create(S.Context, Kind, AL));
}
+static void handleAvailableOnlyInDefaultEvalMethod(Sema&S, Decl *D,
+ const ParsedAttr &AL) {
+ assert(isa<TypedefNameDecl>(D) && "This attribute only applies to a typedef");
+ handleSimpleAttribute<AvailableOnlyInDefaultEvalMethodAttr>(S, D, AL);
+}
+
static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// The 'sycl_kernel' attribute applies only to function templates.
const auto *FD = cast<FunctionDecl>(D);
@@ -9138,6 +9144,9 @@
case ParsedAttr::AT_FunctionReturnThunks:
handleFunctionReturnThunksAttr(S, D, AL);
break;
+ case ParsedAttr::AT_AvailableOnlyInDefaultEvalMethod:
+ handleAvailableOnlyInDefaultEvalMethod(S, D, AL);
+ break;
// Microsoft attributes:
case ParsedAttr::AT_LayoutVersion:
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11499,6 +11499,10 @@
def err_objc_type_args_wrong_arity : Error<
"too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">;
+
+def err_type_available_only_in_default_eval_method : Error<
+ "cannot use type '%0' within '#pragma clang fp eval_method'; type is set "
+ "according to the default eval method for the translation unit">;
}
def err_objc_type_arg_not_id_compatible : Error<
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -4150,3 +4150,9 @@
let Subjects = SubjectList<[Record]>;
let Documentation = [ReadOnlyPlacementDocs];
}
+
+def AvailableOnlyInDefaultEvalMethod : InheritableAttr {
+ let Spellings = [Clang<"available_only_in_default_eval_method">];
+ let Subjects = SubjectList<[TypedefName], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4320,6 +4320,13 @@
a = b[i] * c[i] + e;
}
+Note: the types ``float_t`` and ``double_t`` are defined in the math header file.
+Their definition changes with the eval method. If they are used inside a scope
+containing a ``#pragma clang fp eval_method`` their definition end up being
+different than what the user might have intended. This can potentially generate
+incorrect code, leading to an ABI mismatch. This case is prevented by emitting a
+diagnostic.
+
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 or
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits