36 changes: 18 additions & 18 deletions clang/test/CodeGenCXX/type_visibility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ namespace temp0 {
template struct B<A>;
// FUNS-LABEL: define weak_odr void @_ZN5temp01BINS_1AEE3fooEv(
// VARS: @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant
// VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant
// VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr constant
// VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant
// FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp01BINS_1AEE3fooEv(
// VARS-HIDDEN: @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant
}

namespace temp1 {
Expand All @@ -43,12 +43,12 @@ namespace temp1 {
template struct B<A>;
// FUNS-LABEL: define weak_odr void @_ZN5temp11BINS_1AEE3fooEv(
// VARS: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
// VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
// VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr constant
// VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
// FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp11BINS_1AEE3fooEv(
// VARS-HIDDEN: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
// VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr constant
// VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
}

namespace temp2 {
Expand All @@ -60,12 +60,12 @@ namespace temp2 {
template struct B<A>;
// FUNS-LABEL: define weak_odr void @_ZN5temp21BINS_1AEE3fooEv(
// VARS: @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant
// VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant
// VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr constant
// VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant
// FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp21BINS_1AEE3fooEv(
// VARS-HIDDEN: @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant
}

namespace temp3 {
Expand All @@ -77,12 +77,12 @@ namespace temp3 {
template struct B<A>;
// FUNS-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
// VARS: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
// VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
// VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
// FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
// VARS-HIDDEN: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
}

namespace temp4 {
Expand All @@ -94,12 +94,12 @@ namespace temp4 {
template struct B<A>;
// FUNS-LABEL: define weak_odr void @_ZN5temp41BINS_1AEE3fooEv(
// VARS: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
// VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
// VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
// FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp41BINS_1AEE3fooEv(
// VARS-HIDDEN: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
// VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
}

namespace type0 {
Expand All @@ -110,12 +110,12 @@ namespace type0 {
void A::foo() {}
// FUNS-LABEL: define void @_ZN5type01A3fooEv(
// VARS: @_ZTVN5type01AE = unnamed_addr constant
// VARS: @_ZTSN5type01AE = constant
// VARS: @_ZTIN5type01AE = constant
// VARS: @_ZTSN5type01AE = constant
// FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv(
// VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type01AE = constant
// VARS-HIDDEN: @_ZTIN5type01AE = constant
// VARS-HIDDEN: @_ZTSN5type01AE = constant
}

namespace type1 {
Expand All @@ -126,12 +126,12 @@ namespace type1 {
void A::foo() {}
// FUNS-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS: @_ZTVN5type11AE = unnamed_addr constant
// VARS: @_ZTSN5type11AE = constant
// VARS: @_ZTIN5type11AE = constant
// VARS: @_ZTSN5type11AE = constant
// FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type11AE = constant
// VARS-HIDDEN: @_ZTIN5type11AE = constant
// VARS-HIDDEN: @_ZTSN5type11AE = constant
}

namespace type2 {
Expand All @@ -142,12 +142,12 @@ namespace type2 {
void A::foo() {}
// FUNS-LABEL: define void @_ZN5type21A3fooEv(
// VARS: @_ZTVN5type21AE = hidden unnamed_addr constant
// VARS: @_ZTSN5type21AE = hidden constant
// VARS: @_ZTIN5type21AE = hidden constant
// VARS: @_ZTSN5type21AE = hidden constant
// FUNS-HIDDEN-LABEL: define hidden void @_ZN5type21A3fooEv(
// VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type21AE = hidden constant
// VARS-HIDDEN: @_ZTIN5type21AE = hidden constant
// VARS-HIDDEN: @_ZTSN5type21AE = hidden constant
}

namespace type3 {
Expand All @@ -158,11 +158,11 @@ namespace type3 {
void A::foo() {}
// FUNS-LABEL: define void @_ZN5type31A3fooEv(
// VARS: @_ZTVN5type31AE = hidden unnamed_addr constant
// VARS: @_ZTSN5type31AE = hidden constant
// VARS: @_ZTIN5type31AE = hidden constant
// VARS: @_ZTSN5type31AE = hidden constant
// FUNS-HIDDEN-LABEL: define void @_ZN5type31A3fooEv(
// VARS-HIDDEN: @_ZTVN5type31AE = hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type31AE = hidden constant
// VARS-HIDDEN: @_ZTIN5type31AE = hidden constant
// VARS-HIDDEN: @_ZTSN5type31AE = hidden constant
}

4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/typeinfo-with-address-space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ class B : A {
// NO-AS: @_ZTISt9type_info = external constant ptr
// AS: @_ZTIi = external addrspace(1) constant ptr addrspace(1)
// NO-AS: @_ZTIi = external constant ptr
// AS: @_ZTI1A = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, comdat, align 8
// NO-AS: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat, align 8
// AS: @_ZTVN10__cxxabiv117__class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)]
// NO-AS: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
// AS: @_ZTS1A = linkonce_odr addrspace(1) constant [3 x i8] c"1A\00", comdat, align 1
// NO-AS: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1
// AS: @_ZTI1A = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, comdat, align 8
// NO-AS: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat, align 8
// AS: @_ZTIf = external addrspace(1) constant ptr addrspace(1)
// NO-AS: @_ZTIf = external constant ptr

Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenCXX/visibility-ms-compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ namespace test0 {
// CHECK: declare void @_ZN5test01A3barEv()

const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZN5test02tiE = hidden constant
}

Expand All @@ -40,8 +40,8 @@ namespace test1 {
// CHECK: declare hidden void @_ZN5test11A3barEv()

const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZN5test12tiE = hidden constant
}

Expand All @@ -56,8 +56,8 @@ namespace test2 {
// CHECK: declare void @_ZN5test21A3barEv()

const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZN5test22tiE = hidden constant
}

Expand All @@ -73,8 +73,8 @@ namespace test3 {
// CHECK: declare void @_ZN5test31BINS_1AEE3barEv()

const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant
}

namespace test4 {
Expand All @@ -89,8 +89,8 @@ namespace test4 {
// CHECK: declare void @_ZN5test41BINS_1AEE3barEv()

const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr constant
// CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant
}

namespace test5 {
Expand All @@ -105,6 +105,6 @@ namespace test5 {
// CHECK: declare hidden void @_ZN5test51BINS_1AEE3barEv()

const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant
}
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/vtable-align-address-space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ struct A {
void A::f() {}

// CHECK: @_ZTV1A ={{.*}} unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1A, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1hEv to ptr addrspace(1))]
// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
// CHECK: @_ZTI1A ={{.*}} addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, align 8
// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/vtable-align.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ struct A {
void A::f() {}

// CHECK-32: @_ZTV1A ={{.*}} unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A1fEv, ptr @_ZN1A1gEv, ptr @_ZN1A1hEv] }, align 4
// CHECK-32: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
// CHECK-32: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 2), ptr @_ZTS1A }, align 4
// CHECK-32: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
// CHECK-64: @_ZTV1A ={{.*}} unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A1fEv, ptr @_ZN1A1gEv, ptr @_ZN1A1hEv] }, align 8
// CHECK-64: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
// CHECK-64: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, align 8
// CHECK-64: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/vtable-available-externally.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ void g() {
// This tests mainly that the typeinfo and typename constants have their linkage
// updated correctly.

// CHECK-TEST2: @_ZTSN5Test21AE ={{.*}} constant
// CHECK-TEST2: @_ZTIN5Test21AE ={{.*}} constant
// CHECK-TEST2: @_ZTSN5Test21AE ={{.*}} constant
// CHECK-TEST2: @_ZTVN5Test21AE ={{.*}} unnamed_addr constant
namespace Test2 {
struct A {
Expand Down
24 changes: 12 additions & 12 deletions clang/test/CodeGenCXX/vtable-key-function-arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ struct Test2a {
// V-table should be defined with strong linkage.
Test2a::Test2a() { use(typeid(Test2a)); }
// CHECK: @_ZTV6Test2a ={{.*}} unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2a ={{.*}} constant
// CHECK-LATE: @_ZTI6Test2a ={{.*}} constant
// CHECK-LATE: @_ZTS6Test2a ={{.*}} constant

// 'bar' becomes the key function when 'foo' is defined inline.
void Test2a::bar() {}
Expand All @@ -111,8 +111,8 @@ void Test2b::bar() {}
// V-table should be defined with strong linkage.
Test2b::Test2b() { use(typeid(Test2b)); }
// CHECK: @_ZTV6Test2b ={{.*}} unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2b ={{.*}} constant
// CHECK-LATE: @_ZTI6Test2b ={{.*}} constant
// CHECK-LATE: @_ZTS6Test2b ={{.*}} constant

inline void Test2b::foo() {}

Expand All @@ -131,8 +131,8 @@ inline void Test2c::foo() {}
// V-table should be defined with strong linkage.
Test2c::Test2c() { use(typeid(Test2c)); }
// CHECK: @_ZTV6Test2c ={{.*}} unnamed_addr constant
// CHECK: @_ZTS6Test2c ={{.*}} constant
// CHECK: @_ZTI6Test2c ={{.*}} constant
// CHECK: @_ZTS6Test2c ={{.*}} constant

/*** Test3a ******************************************************************/

Expand All @@ -145,8 +145,8 @@ struct Test3a {
// V-table should be defined with weak linkage.
Test3a::Test3a() { use(typeid(Test3a)); }
// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant

// There ceases to be a key function after these declarations.
inline void Test3a::bar() {}
Expand All @@ -166,8 +166,8 @@ inline void Test3b::bar() {}
// V-table should be defined with weak linkage.
Test3b::Test3b() { use(typeid(Test3b)); }
// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant

inline void Test3b::foo() {}

Expand All @@ -186,8 +186,8 @@ inline void Test3c::foo() {}
// V-table should be defined with weak linkage.
Test3c::Test3c() { use(typeid(Test3c)); }
// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test3c = linkonce_odr constant
// CHECK: @_ZTI6Test3c = linkonce_odr constant
// CHECK: @_ZTS6Test3c = linkonce_odr constant

/*** Test4a ******************************************************************/

Expand All @@ -200,8 +200,8 @@ template <class T> struct Test4a {
// V-table should be defined with weak linkage.
template <> Test4a<int>::Test4a() { use(typeid(Test4a)); }
// CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant
// CHECK: @_ZTI6Test4aIiE = linkonce_odr constant
// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant

// There ceases to be a key function after these declarations.
template <> inline void Test4a<int>::bar() {}
Expand All @@ -221,8 +221,8 @@ template <> inline void Test4b<int>::bar() {}
// V-table should be defined with weak linkage.
template <> Test4b<int>::Test4b() { use(typeid(Test4b)); }
// CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant
// CHECK: @_ZTI6Test4bIiE = linkonce_odr constant
// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant

template <> inline void Test4b<int>::foo() {}

Expand All @@ -241,8 +241,8 @@ template <> inline void Test4c<int>::foo() {}
// V-table should be defined with weak linkage.
template <> Test4c<int>::Test4c() { use(typeid(Test4c)); }
// CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant
// CHECK: @_ZTI6Test4cIiE = linkonce_odr constant
// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant

/*** Test5a ******************************************************************/

Expand All @@ -258,8 +258,8 @@ template <> inline void Test5a<int>::foo();
// V-table should be defined with weak linkage.
template <> Test5a<int>::Test5a() { use(typeid(Test5a)); }
// CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant
// CHECK: @_ZTI6Test5aIiE = linkonce_odr constant
// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant

// There ceases to be a key function after these declarations.
template <> inline void Test5a<int>::bar() {}
Expand All @@ -280,8 +280,8 @@ template <> inline void Test5b<int>::bar() {}
// V-table should be defined with weak linkage.
template <> Test5b<int>::Test5b() { use(typeid(Test5b)); }
// CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant
// CHECK: @_ZTI6Test5bIiE = linkonce_odr constant
// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant

template <> inline void Test5a<int>::foo();
template <> inline void Test5b<int>::foo() {}
Expand All @@ -303,5 +303,5 @@ template <> inline void Test5c<int>::foo() {}
// V-table should be defined with weak linkage.
template <> Test5c<int>::Test5c() { use(typeid(Test5c)); }
// CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant
// CHECK: @_ZTI6Test5cIiE = linkonce_odr constant
// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant
16 changes: 8 additions & 8 deletions clang/test/CodeGenCXX/vtable-key-function-ios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ struct Test1a {
// V-table needs to be defined weakly.
Test1a::Test1a() { use(typeid(Test1a)); }
// CHECK: @_ZTV6Test1a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK-LATE: @_ZTS6Test1a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTI6Test1a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTS6Test1a = linkonce_odr {{(dso_local )?}}constant

// This defines the key function.
inline void Test1a::foo() {}
Expand All @@ -83,8 +83,8 @@ inline void Test1b::foo() {}
// V-table should be defined weakly..
Test1b::Test1b() { use(typeid(Test1b)); }
// CHECK: @_ZTV6Test1b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK: @_ZTS6Test1b = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTI6Test1b = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTS6Test1b = linkonce_odr {{(dso_local )?}}constant

/*** Test2a ******************************************************************/

Expand All @@ -97,8 +97,8 @@ struct Test2a {
// V-table should be defined with weak linkage.
Test2a::Test2a() { use(typeid(Test2a)); }
// CHECK: @_ZTV6Test2a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTI6Test2a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTS6Test2a = linkonce_odr {{(dso_local )?}}constant

void Test2a::bar() {}
inline void Test2a::foo() {}
Expand All @@ -116,8 +116,8 @@ void Test2b::bar() {}
// V-table should be defined with weak linkage.
Test2b::Test2b() { use(typeid(Test2b)); }
// CHECK: @_ZTV6Test2b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2b = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTI6Test2b = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTS6Test2b = linkonce_odr {{(dso_local )?}}constant

inline void Test2b::foo() {}

Expand All @@ -135,8 +135,8 @@ inline void Test2c::foo() {}
// V-table should be defined with weak linkage.
Test2c::Test2c() { use(typeid(Test2c)); }
// CHECK: @_ZTV6Test2c = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK: @_ZTS6Test2c = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTI6Test2c = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTS6Test2c = linkonce_odr {{(dso_local )?}}constant

/*** Test3a ******************************************************************/

Expand All @@ -149,8 +149,8 @@ struct Test3a {
// V-table should be defined with weak linkage.
Test3a::Test3a() { use(typeid(Test3a)); }
// CHECK: @_ZTV6Test3a = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTI6Test3a = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr {{(dso_local )?}}constant

// This defines the key function.
inline void Test3a::bar() {}
Expand All @@ -169,8 +169,8 @@ inline void Test3b::bar() {}
// V-table should be defined with weak linkage.
Test3b::Test3b() { use(typeid(Test3b)); }
// CHECK: @_ZTV6Test3b = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTI6Test3b = linkonce_odr {{(dso_local )?}}constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr {{(dso_local )?}}constant

// This defines the key function.
inline void Test3b::foo() {}
Expand All @@ -190,5 +190,5 @@ inline void Test3c::foo() {}
// V-table should be defined with weak linkage.
Test3c::Test3c() { use(typeid(Test3c)); }
// CHECK: @_ZTV6Test3c = linkonce_odr {{(dso_local )?}}unnamed_addr constant
// CHECK: @_ZTS6Test3c = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTI6Test3c = linkonce_odr {{(dso_local )?}}constant
// CHECK: @_ZTS6Test3c = linkonce_odr {{(dso_local )?}}constant
6 changes: 3 additions & 3 deletions clang/test/CodeGenCXX/vtable-key-function-win-comdat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ Test1a::Test1a() { use(typeid(Test1a)); }
inline void Test1a::foo() {}

// CHECK: $_ZTV6Test1a = comdat any
// CHECK: $_ZTS6Test1a = comdat any
// CHECK: $_ZTI6Test1a = comdat any
// CHECK-NOT: $_ZTS6Test1a.1 = comdat any
// CHECK: $_ZTS6Test1a = comdat any
// CHECK-NOT: $_ZTI6Test1a.1 = comdat any
// CHECK-NOT: $_ZTS6Test1a.1 = comdat any

// CHECK: @_ZTV6Test1a = linkonce_odr dso_local unnamed_addr constant {{.*}} ptr @_ZTI6Test1a
// CHECK: @_ZTS6Test1a = linkonce_odr dso_local constant
// CHECK: @_ZTI6Test1a = linkonce_odr dso_local constant {{.*}} ptr @_ZTS6Test1a
// CHECK: @_ZTS6Test1a = linkonce_odr dso_local constant
14 changes: 7 additions & 7 deletions clang/test/CodeGenCXX/weak-extern-typeinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ class V2 : public virtual V1 {
void V1::foo() { }
void V2::foo() { }

// CHECK: @_ZTS1A = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1A = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1B = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1A = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1B = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1B = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1C = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1C = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2T1 = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI2T1 = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1T = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2T1 = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1T = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1C = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2V1 = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1T = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI2V1 = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2V2 = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2V1 = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI2V2 = weak_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS2V2 = weak_odr {{(dso_local |hidden )?}}constant
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/windows-itanium-type-info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ void f() {

// CHECK-DAG: @_ZTI4base = external dllimport constant

// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr dso_local constant
// CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr dso_local constant
// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr dso_local constant

struct __declspec(dllimport) gatekeeper {};
struct zuul : gatekeeper {
Expand Down
9 changes: 5 additions & 4 deletions clang/test/CodeGenObjCXX/rtti.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@

namespace std { class type_info; }

// CHECK: @_ZTI1A = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A
@interface A
@end

// CHECK: @_ZTI1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A
@interface B : A
@end

// CHECK: @_ZTIP1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP1B{{.*}}, i32 0, {{.*}}@_ZTI1B
// CHECK: @_ZTI11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object
// CHECK: @_ZTI1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A
// CHECK: @_ZTI1A = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A

// CHECK: @_ZTIP11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP11objc_object{{.*}}@_ZTI11objc_object
// CHECK: @_ZTI10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class
// CHECK: @_ZTI11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object
// CHECK: @_ZTIP10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP10objc_class{{.*}}@_ZTI10objc_class
// CHECK: @_ZTI10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class

@protocol P;

Expand Down
57 changes: 54 additions & 3 deletions clang/test/Driver/stack-protector-guard.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
// RUN: FileCheck -check-prefix=CHECK-SYM %s

// Invalid arch
// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
// RUN: not %clang -target mipsel-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-ARCH %s
// INVALID-ARCH: unsupported option '-mstack-protector-guard=tls' for target

// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-reg=fs %s 2>&1 | \
// RUN: not %clang -target mipsel-linux-gnu -mstack-protector-guard-reg=fs %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-ARCH2 %s
// INVALID-ARCH2: unsupported option '-mstack-protector-guard-reg=fs' for target

// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \
// RUN: not %clang -target mipsel-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-ARCH3 %s
// INVALID-ARCH3: unsupported option '-mstack-protector-guard-offset=10' for target

Expand Down Expand Up @@ -104,3 +104,54 @@
// RUN: FileCheck -check-prefix=INVALID-REG-RISCV %s

// INVALID-REG-RISCV: error: invalid value 'sp' in 'mstack-protector-guard-reg=', expected one of: tp

// RUN: %clang -### -target powerpc64-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r13 %s 2>&1 | \
// RUN: FileCheck -v -check-prefix=CHECK-TLS-POWERPC64 %s
// RUN: %clang -### -target powerpc64-unknown-linux-gnu -mstack-protector-guard=global %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s

// RUN: not %clang -target powerpc64-unknown-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \
// RUN: FileCheck -check-prefix=MISSING-OFFSET %s

// RUN: not %clang -target powerpc64-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-VALUE2 %s

// RUN: not %clang -target powerpc64-unknown-elf -mstack-protector-guard=tls \
// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r12 %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-REG-POWERPC64 %s

// CHECK-TLS-POWERPC64: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r13"
// INVALID-REG-POWERPC64: error: invalid value 'r12' in 'mstack-protector-guard-reg=', expected one of: r13

// RUN: %clang -### -target powerpc64le-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r13 %s 2>&1 | \
// RUN: FileCheck -v -check-prefix=CHECK-TLS-POWERPC64 %s
// RUN: %clang -### -target powerpc64le-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s

// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
// RUN: FileCheck -check-prefix=MISSING-OFFSET %s

// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-VALUE2 %s

// RUN: not %clang -target powerpc64le-unknown-elf -mstack-protector-guard=tls \
// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r12 %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-REG-POWERPC64 %s

// RUN: %clang -### -target ppc32-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=r2 %s 2>&1 | \
// RUN: FileCheck -v -check-prefix=CHECK-TLS-POWERPC32 %s
// RUN: %clang -### -target ppc32-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s

// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
// RUN: FileCheck -check-prefix=MISSING-OFFSET %s

// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-VALUE2 %s

// RUN: not %clang -target ppc32-unknown-elf -mstack-protector-guard=tls \
// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=r3 %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID-REG-POWERPC32 %s

// CHECK-TLS-POWERPC32: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r2"
// INVALID-REG-POWERPC32: error: invalid value 'r3' in 'mstack-protector-guard-reg=', expected one of: r2
2 changes: 1 addition & 1 deletion clang/test/Modules/no-external-type-id.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export module b;
import a;
export int b();

// CHECK: <DECL_FUNCTION {{.*}} op8=4064
// CHECK: <DECL_FUNCTION {{.*}} op8=4088
// CHECK: <TYPE_FUNCTION_PROTO

//--- a.v1.cppm
Expand Down
6 changes: 3 additions & 3 deletions clang/test/Modules/pr97313.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ auto v6 = new Template<NonTemplate>();
// CHECK: @_ZTVW3Mod11NonTemplate = {{.*}}external
// CHECK: @_ZTVW3Mod8TemplateIcE = {{.*}}external
// CHECK: @_ZTVW3Mod8TemplateIjE = {{.*}}weak_odr
// CHECK: @_ZTSW3Mod8TemplateIjE = {{.*}}weak_odr
// CHECK: @_ZTIW3Mod8TemplateIjE = {{.*}}weak_odr
// CHECK: @_ZTSW3Mod8TemplateIjE = {{.*}}weak_odr
// CHECK: @_ZTVW3Mod8TemplateIdE = {{.*}}external
// CHECK: @_ZTVW3Mod8TemplateIiE = {{.*}}linkonce_odr
// CHECK: @_ZTSW3Mod8TemplateIiE = {{.*}}linkonce_odr
// CHECK: @_ZTIW3Mod8TemplateIiE = {{.*}}linkonce_odr
// CHECK: @_ZTSW3Mod8TemplateIiE = {{.*}}linkonce_odr
// CHECK: @_ZTVW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
// CHECK: @_ZTSW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
// CHECK: @_ZTIW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
// CHECK: @_ZTSW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr
13 changes: 12 additions & 1 deletion clang/test/Sema/constant-builtins-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ long double g11 = __builtin_nansl("");
__float128 g11_2 = __builtin_nansf128("");
#endif

//int g12 = __builtin_abs(-12);
int g12 = __builtin_abs(-12);

double g13 = __builtin_fabs(-12.);
double g13_0 = __builtin_fabs(-0.);
Expand Down Expand Up @@ -456,6 +456,17 @@ char clrsb9[__builtin_clrsb(1 << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
char clrsb10[__builtin_clrsb(~(1 << (BITSIZE(int) - 1))) == 0 ? 1 : -1];
char clrsb11[__builtin_clrsb(0xf) == BITSIZE(int) - 5 ? 1 : -1];
char clrsb12[__builtin_clrsb(~0x1f) == BITSIZE(int) - 6 ? 1 : -1];

char abs1[__builtin_abs(-12)];
char abs2[__builtin_labs(-12L)];
char abs3[__builtin_llabs(-12LL)];
int abs4 = __builtin_abs(1 << (BITSIZE(int) - 1)); // expected-error {{not a compile-time constant}}
char abs5[__builtin_abs((1 << (BITSIZE(int) - 1)) + 1)];
long abs6 = __builtin_labs(1L << (BITSIZE(long) - 1)); // expected-error {{not a compile-time constant}}
long abs7 = __builtin_labs((1L << (BITSIZE(long) - 1)) + 1);
long long abs8 = __builtin_llabs(1LL << (BITSIZE(long long) - 1)); // expected-error {{not a compile-time constant}}
long long abs9 = __builtin_llabs((1LL << (BITSIZE(long long) - 1)) + 1);

#undef BITSIZE

// GCC misc stuff
Expand Down
17 changes: 17 additions & 0 deletions clang/test/Sema/constexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,20 @@ void constexprif() {
void constevalif() {
if consteval (300) {} //expected-error {{expected '(' after 'if'}}
}

struct S11 {
int len;
};
void ghissue112516() {
struct S11 *s11 = 0;
constexpr int num = s11->len; // expected-error {{constexpr variable 'num' must be initialized by a constant expression}}
void *Arr[num];
}

void ghissue109095() {
constexpr char c[] = { 'a' };
constexpr int i = c[1]; // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}\
// expected-note {{declared here}}
_Static_assert(i == c[0]); // expected-error {{static assertion expression is not an integral constant expression}}\
// expected-note {{initializer of 'i' is not a constant expression}}
}
17 changes: 17 additions & 0 deletions clang/test/SemaCXX/cxx2b-deducing-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,3 +1097,20 @@ struct C4 {
// expected-warning {{volatile-qualified parameter type 'const volatile C4' is deprecated}}
};
}


namespace GH112559 {
struct Wrap {};
struct S {
constexpr operator Wrap (this const S& self) {
return Wrap{};
};
constexpr int operator <<(this Wrap self, int i) {
return 0;
}
};
// Purposefully invalid expression to check an assertion in the
// expression recovery machinery.
static_assert((S{} << 11) == a);
// expected-error@-1 {{use of undeclared identifier 'a'}}
}
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/typeid-ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace std {
struct X { };

void f() {
// CHECK: @_ZTS1X = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTI1X = linkonce_odr {{(dso_local |hidden )?}}constant
// CHECK: @_ZTS1X = linkonce_odr {{(dso_local |hidden )?}}constant
(void)typeid(X&);
}
28 changes: 28 additions & 0 deletions clang/unittests/AST/ASTImporterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9986,6 +9986,34 @@ TEST_P(ImportTemplateParmDeclDefaultValue, InvisibleInheritedFrom) {
ToFDef->getTemplateParameters()->getParam(0));
}

TEST_P(ImportTemplateParmDeclDefaultValue, DefValImportError) {
const char *ToCode =
R"(
class X {
int A;
};
)";
getToTuDecl(ToCode, Lang_CXX14);

const char *FromCode =
R"(
class X;

template <typename P = X>
void f() {}

class X {
char A;
};
)";
TranslationUnitDecl *FromTU = getTuDecl(FromCode, Lang_CXX14);
auto *FromF = FirstDeclMatcher<FunctionTemplateDecl>().match(
FromTU, functionTemplateDecl(hasName("f")));

auto *ToFImported = Import(FromF, Lang_CXX14);
EXPECT_FALSE(ToFImported);
}

TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {
TranslationUnitDecl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);
auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
Expand Down
5 changes: 5 additions & 0 deletions clang/unittests/Basic/DiagnosticTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
using namespace llvm;
using namespace clang;

// Declare DiagnosticsTestHelper to avoid GCC warning
namespace clang {
void DiagnosticsTestHelper(DiagnosticsEngine &diag);
}

void clang::DiagnosticsTestHelper(DiagnosticsEngine &diag) {
EXPECT_FALSE(diag.DiagStates.empty());
EXPECT_TRUE(diag.DiagStatesByLoc.empty());
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
CHECK_PARSE_BOOL(RemoveBracesLLVM);
CHECK_PARSE_BOOL(RemoveEmptyLinesInUnwrappedLines);
CHECK_PARSE_BOOL(RemoveSemicolon);
CHECK_PARSE_BOOL(SkipMacroDefinitionBody);
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
Expand Down
77 changes: 77 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28135,6 +28135,83 @@ TEST_F(FormatTest, BreakBinaryOperations) {
Style);
}

TEST_F(FormatTest, RemovesEmptyLinesInUnwrappedLines) {
auto Style = getLLVMStyle();
Style.RemoveEmptyLinesInUnwrappedLines = true;

verifyFormat("int c = a + b;",
"int c\n"
"\n"
" = a + b;",
Style);

verifyFormat("enum : unsigned { AA = 0, BB } myEnum;",
"enum : unsigned\n"
"\n"
"{\n"
" AA = 0,\n"
" BB\n"
"} myEnum;",
Style);

verifyFormat("class B : public E {\n"
"private:\n"
"};",
"class B : public E\n"
"\n"
"{\n"
"private:\n"
"};",
Style);

verifyFormat(
"struct AAAAAAAAAAAAAAA test[3] = {{56, 23, \"hello\"}, {7, 5, \"!!\"}};",
"struct AAAAAAAAAAAAAAA test[3] = {{56,\n"
"\n"
" 23, \"hello\"},\n"
" {7, 5, \"!!\"}};",
Style);

verifyFormat("int myFunction(int aaaaaaaaaaaaa, int ccccccccccccc, int d);",
"int myFunction(\n"
"\n"
" int aaaaaaaaaaaaa,\n"
"\n"
" int ccccccccccccc, int d);",
Style);

verifyFormat("switch (e) {\n"
"case 1:\n"
" return e;\n"
"case 2:\n"
" return 2;\n"
"}",
"switch (\n"
"\n"
" e) {\n"
"case 1:\n"
" return e;\n"
"case 2:\n"
" return 2;\n"
"}",
Style);

verifyFormat("while (true) {\n"
"}",
"while (\n"
"\n"
" true) {\n"
"}",
Style);

verifyFormat("void loooonFunctionIsVeryLongButNotAsLongAsJavaTypeNames(\n"
" std::map<int, std::string> *outputMap);",
"void loooonFunctionIsVeryLongButNotAsLongAsJavaTypeNames\n"
"\n"
" (std::map<int, std::string> *outputMap);",
Style);
}

} // namespace
} // namespace test
} // namespace format
Expand Down
6 changes: 6 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3554,6 +3554,12 @@ TEST_F(TokenAnnotatorTest, TemplateInstantiation) {
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[16], tok::greater, TT_TemplateCloser);

Tokens =
annotate("auto x{std::conditional_t<T::value == U::value, T, U>{}};");
ASSERT_EQ(Tokens.size(), 24u) << Tokens;
EXPECT_TOKEN(Tokens[6], tok::less, TT_TemplateOpener);
EXPECT_TOKEN(Tokens[18], tok::greater, TT_TemplateCloser);
}

} // namespace
Expand Down
4 changes: 2 additions & 2 deletions clang/utils/TableGen/ClangOptionDocEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,13 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
for (const Record *VisibilityHelp :
R->getValueAsListOfDefs("HelpTextsForVariants")) {
// This is a list of visibilities.
ArrayRef<Init *> Visibilities =
ArrayRef<const Init *> Visibilities =
VisibilityHelp->getValueAsListInit("Visibilities")->getValues();

// See if any of the program's visibilities are in the list.
for (StringRef DocInfoMask :
DocInfo->getValueAsListOfStrings("VisibilityMask")) {
for (Init *Visibility : Visibilities) {
for (const Init *Visibility : Visibilities) {
if (Visibility->getAsUnquotedString() == DocInfoMask) {
// Use the first one we find.
Description = escapeRST(VisibilityHelp->getValueAsString("Text"));
Expand Down
4 changes: 2 additions & 2 deletions clang/utils/TableGen/RISCVVEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static VectorTypeModifier getTupleVTM(unsigned NF) {

static unsigned getIndexedLoadStorePtrIdx(const RVVIntrinsic *RVVI) {
// We need a special rule for segment load/store since the data width is not
// encoded in the instrinsic name itself.
// encoded in the intrinsic name itself.
const StringRef IRName = RVVI->getIRName();
constexpr unsigned RVV_VTA = 0x1;
constexpr unsigned RVV_VMA = 0x2;
Expand All @@ -192,7 +192,7 @@ static unsigned getIndexedLoadStorePtrIdx(const RVVIntrinsic *RVVI) {
static unsigned getSegInstLog2SEW(StringRef InstName) {
// clang-format off
// We need a special rule for indexed segment load/store since the data width
// is not encoded in the instrinsic name itself.
// is not encoded in the intrinsic name itself.
if (InstName.starts_with("vloxseg") || InstName.starts_with("vluxseg") ||
InstName.starts_with("vsoxseg") || InstName.starts_with("vsuxseg"))
return (unsigned)-1;
Expand Down
4 changes: 4 additions & 0 deletions clang/utils/TableGen/SveEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,10 @@ void SVEEmitter::createHeader(raw_ostream &OS) {
OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n";
OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n";

OS << "typedef __clang_svmfloat8x2_t svmfloat8x2_t;\n";
OS << "typedef __clang_svmfloat8x3_t svmfloat8x3_t;\n";
OS << "typedef __clang_svmfloat8x4_t svmfloat8x4_t;\n";

OS << "typedef __SVCount_t svcount_t;\n\n";

OS << "enum svpattern\n";
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/interception/interception_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
}

switch (*(u32*)(address)) {
case 0x1ab60f44: // 44 0f b6 1a : movzx r11d, BYTE PTR [rdx]
case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/test/lsan/TestCases/print_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

// XFAIL: hwasan

// No pthread barriers on Darwin.
// UNSUPPORTED: darwin

#include <assert.h>
#include <pthread.h>
#include <sanitizer/lsan_interface.h>
Expand Down
2 changes: 1 addition & 1 deletion flang/docs/OptionComparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ eN
</td>
<td>fdec,
<p>
fall-instrinsics
fall-intrinsics
</td>
<td><a href="https://www-01.ibm.com/support/docview.wss?uid=swg27024803&aid=1#page=297">qxlf77</a>,
<p>
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Common/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ LANGOPT(Name, Bits, Default)
#endif

ENUM_LANGOPT(FPContractMode, FPModeKind, 2, FPM_Fast) ///< FP Contract Mode (off/fast)
/// signed integer overflow handling
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 1, SOB_Undefined)

/// Indicate a build without the standard GPU libraries.
LANGOPT(NoGPULib , 1, false)
Expand Down
8 changes: 8 additions & 0 deletions flang/include/flang/Common/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ namespace Fortran::common {
class LangOptionsBase {

public:
enum SignedOverflowBehaviorTy {
// -fno-wrapv (default behavior in Flang)
SOB_Undefined,

// -fwrapv
SOB_Defined,
};

enum FPModeKind {
// Do not fuse FP ops
FPM_Off,
Expand Down
5 changes: 2 additions & 3 deletions flang/include/flang/Lower/LoweringOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ ENUM_LOWERINGOPT(NoPPCNativeVecElemOrder, unsigned, 1, 0)
ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)

/// If true, assume the behavior of integer overflow is defined
/// (i.e. wraps around as two's complement). On by default.
/// TODO: make the default off
ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 1)
/// (i.e. wraps around as two's complement). Off by default.
ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 0)

/// If true, add nsw flags to loop variable increments.
/// Off by default.
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/PPCIntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ struct VecTypeInfo {
static inline VecTypeInfo getVecTypeFromFirType(mlir::Type firTy) {
assert(mlir::isa<fir::VectorType>(firTy));
VecTypeInfo vecTyInfo;
vecTyInfo.eleTy = mlir::dyn_cast<fir::VectorType>(firTy).getEleTy();
vecTyInfo.eleTy = mlir::dyn_cast<fir::VectorType>(firTy).getElementType();
vecTyInfo.len = mlir::dyn_cast<fir::VectorType>(firTy).getLen();
return vecTyInfo;
}
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ def fir_SequenceType : FIR_Type<"Sequence", "array"> {
size = size * static_cast<std::uint64_t>(extent);
return size;
}

mlir::Type getElementType() const { return getEleTy(); }
}];
}

Expand Down Expand Up @@ -519,6 +521,8 @@ def fir_VectorType : FIR_Type<"Vector", "vector"> {

let extraClassDeclaration = [{
static bool isValidElementType(mlir::Type t);

mlir::Type getElementType() const { return getEleTy(); }
}];

let skipDefaultBuilders = 1;
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "llvm/Frontend/OpenACC/ACC.h.inc"
#include "llvm/Frontend/OpenMP/OMP.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include <cinttypes>
#include <list>
Expand Down Expand Up @@ -3660,6 +3661,7 @@ struct OmpLastprivateClause {
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
llvm::omp::Clause Id() const;

#define GEN_FLANG_CLAUSE_PARSER_CLASSES
#include "llvm/Frontend/OpenMP/OMP.inc"
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Runtime/magic-numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ The denorm value is a nonstandard extension.

#if 0
ieee_round_type values
The values are those of the llvm.get.rounding instrinsic, which is assumed by
The values are those of the llvm.get.rounding intrinsic, which is assumed by
ieee_arithmetic module rounding procedures.
#endif
#define _FORTRAN_RUNTIME_IEEE_TO_ZERO 0
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
// MAX and MIN (and others that map to them) allow their last argument to
// be repeated indefinitely. The actualForDummy vector is sized
// and null-initialized to the non-repeated dummy argument count
// for other instrinsics.
// for other intrinsics.
bool isMaxMin{dummyArgPatterns > 0 &&
dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
std::vector<ActualArgument *> actualForDummy(
Expand Down
36 changes: 33 additions & 3 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,24 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
return diags.getNumErrors() == numErrorsBefore;
}

/// Parses signed integer overflow options and populates the
/// CompilerInvocation accordingly.
/// Returns false if new errors are generated.
///
/// \param [out] invoc Stores the processed arguments
/// \param [in] args The compiler invocation arguments to parse
/// \param [out] diags DiagnosticsEngine to report erros with
static bool parseIntegerOverflowArgs(CompilerInvocation &invoc,
llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
Fortran::common::LangOptions &opts = invoc.getLangOpts();

if (args.getLastArg(clang::driver::options::OPT_fwrapv))
opts.setSignedOverflowBehavior(Fortran::common::LangOptions::SOB_Defined);

return true;
}

/// Parses all floating point related arguments and populates the
/// CompilerInvocation accordingly.
/// Returns false if new errors are generated.
Expand Down Expand Up @@ -1255,6 +1273,18 @@ static bool parseLinkerOptionsArgs(CompilerInvocation &invoc,
return true;
}

static bool parseLangOptionsArgs(CompilerInvocation &invoc,
llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
bool success = true;

success &= parseIntegerOverflowArgs(invoc, args, diags);
success &= parseFloatingPointArgs(invoc, args, diags);
success &= parseVScaleArgs(invoc, args, diags);

return success;
}

bool CompilerInvocation::createFromArgs(
CompilerInvocation &invoc, llvm::ArrayRef<const char *> commandLineArgs,
clang::DiagnosticsEngine &diags, const char *argv0) {
Expand Down Expand Up @@ -1363,9 +1393,7 @@ bool CompilerInvocation::createFromArgs(
invoc.frontendOpts.mlirArgs =
args.getAllArgValues(clang::driver::options::OPT_mmlir);

success &= parseFloatingPointArgs(invoc, args, diags);

success &= parseVScaleArgs(invoc, args, diags);
success &= parseLangOptionsArgs(invoc, args, diags);

success &= parseLinkerOptionsArgs(invoc, args, diags);

Expand Down Expand Up @@ -1577,6 +1605,8 @@ void CompilerInvocation::setLoweringOptions() {
loweringOpts.setUnderscoring(codegenOpts.Underscoring);

const Fortran::common::LangOptions &langOptions = getLangOpts();
loweringOpts.setIntegerWrapAround(langOptions.getSignedOverflowBehavior() ==
Fortran::common::LangOptions::SOB_Defined);
Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
// TODO: when LangOptions are finalized, we can represent
// the math related options using Fortran::commmon::MathOptionsBase,
Expand Down
7 changes: 4 additions & 3 deletions flang/lib/Lower/ConvertConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter,
} while (con.IncrementSubscripts(subscripts));
} else if constexpr (T::category == Fortran::common::TypeCategory::Derived) {
do {
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrayTy).getEleTy();
mlir::Type eleTy =
mlir::cast<fir::SequenceType>(arrayTy).getElementType();
mlir::Value elementVal =
genScalarLit(converter, loc, con.At(subscripts), eleTy,
/*outlineInReadOnlyMemory=*/false);
Expand All @@ -594,7 +595,7 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter,
} else {
llvm::SmallVector<mlir::Attribute> rangeStartIdx;
uint64_t rangeSize = 0;
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrayTy).getEleTy();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrayTy).getElementType();
do {
auto getElementVal = [&]() {
return builder.createConvert(loc, eleTy,
Expand Down Expand Up @@ -643,7 +644,7 @@ genOutlineArrayLit(Fortran::lower::AbstractConverter &converter,
mlir::Location loc, mlir::Type arrayTy,
const Fortran::evaluate::Constant<T> &constant) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrayTy).getEleTy();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrayTy).getElementType();
llvm::StringRef globalName = converter.getUniqueLitName(
loc, std::make_unique<Fortran::lower::SomeExpr>(toEvExpr(constant)),
eleTy);
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Lower/ConvertExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,7 @@ class ScalarExprLowering {
mlir::Location loc = getLoc();
mlir::Value addr = fir::getBase(array);
mlir::Type arrTy = fir::dyn_cast_ptrEleTy(addr.getType());
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(eleTy));
mlir::Type refTy = builder.getRefType(eleTy);
mlir::Value base = builder.createConvert(loc, seqTy, addr);
Expand Down Expand Up @@ -1659,7 +1659,7 @@ class ScalarExprLowering {
mlir::Location loc = getLoc();
mlir::Value addr = fir::getBase(exv);
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(addr.getType());
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
mlir::Type refTy = builder.getRefType(eleTy);
mlir::IndexType idxTy = builder.getIndexType();
llvm::SmallVector<mlir::Value> arrayCoorArgs;
Expand Down Expand Up @@ -4145,7 +4145,7 @@ class ArrayExprLowering {
mlir::Location loc = getLoc();
return [=, builder = &converter.getFirOpBuilder()](IterSpace iters) {
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(tmp.getType());
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
mlir::Type eleRefTy = builder->getRefType(eleTy);
mlir::IntegerType i1Ty = builder->getI1Type();
// Adjust indices for any shift of the origin of the array.
Expand Down Expand Up @@ -5759,7 +5759,7 @@ class ArrayExprLowering {
return fir::BoxValue(embox, lbounds, nonDeferredLenParams);
};
}
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
if (isReferentiallyOpaque()) {
// Semantics are an opaque reference to an array.
// This case forwards a continuation that will generate the address
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Lower/ConvertExprToHLFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,8 @@ class HlfirDesignatorBuilder {
return createVectorSubscriptElementAddrOp(partInfo, baseType,
resultExtents);

mlir::Type resultType = mlir::cast<fir::SequenceType>(baseType).getEleTy();
mlir::Type resultType =
mlir::cast<fir::SequenceType>(baseType).getElementType();
if (!resultTypeShape.empty()) {
// Ranked array section. The result shape comes from the array section
// subscripts.
Expand Down Expand Up @@ -811,7 +812,7 @@ class HlfirDesignatorBuilder {
}
}
builder.setInsertionPoint(elementalAddrOp);
return mlir::cast<fir::SequenceType>(baseType).getEleTy();
return mlir::cast<fir::SequenceType>(baseType).getElementType();
}

/// Yield the designator for the final part-ref inside the
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
// type does not support nested structures.
if (mlir::isa<fir::SequenceType>(symTy) &&
!Fortran::semantics::IsAllocatableOrPointer(sym)) {
mlir::Type eleTy = mlir::cast<fir::SequenceType>(symTy).getEleTy();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(symTy).getElementType();
if (mlir::isa<mlir::IntegerType, mlir::FloatType, mlir::ComplexType,
fir::LogicalType>(eleTy)) {
const auto *details =
Expand Down
23 changes: 1 addition & 22 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,6 @@
#include <utility>
#include <variant>

namespace detail {
template <typename C>
llvm::omp::Clause getClauseIdForClass(C &&) {
using namespace Fortran;
using A = llvm::remove_cvref_t<C>; // A is referenced in OMP.inc
// The code included below contains a sequence of checks like the following
// for each OpenMP clause
// if constexpr (std::is_same_v<A, parser::OmpClause::AcqRel>)
// return llvm::omp::Clause::OMPC_acq_rel;
// [...]
#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
#include "llvm/Frontend/OpenMP/OMP.inc"
}
} // namespace detail

static llvm::omp::Clause getClauseId(const Fortran::parser::OmpClause &clause) {
return Fortran::common::visit(
[](auto &&s) { return detail::getClauseIdForClass(s); }, clause.u);
}

namespace Fortran::lower::omp {
using SymbolWithDesignator = std::tuple<semantics::Symbol *, MaybeExpr>;

Expand Down Expand Up @@ -1253,8 +1233,7 @@ Clause makeClause(const parser::OmpClause &cls,
semantics::SemanticsContext &semaCtx) {
return Fortran::common::visit(
[&](auto &&s) {
return makeClause(getClauseId(cls), clause::make(s, semaCtx),
cls.source);
return makeClause(cls.Id(), clause::make(s, semaCtx), cls.source);
},
cls.u);
}
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3824,7 +3824,7 @@ IntrinsicLibrary::genReduction(FN func, FD funcDim, llvm::StringRef errMsg,
if (absentDim || rank == 1) {
mlir::Type ty = array.getType();
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
if (fir::isa_complex(eleTy)) {
mlir::Value result = builder.createTemporary(loc, eleTy);
func(builder, loc, array, mask, result);
Expand Down Expand Up @@ -6137,7 +6137,7 @@ IntrinsicLibrary::genReduce(mlir::Type resultType,

mlir::Type ty = array.getType();
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();

// Handle optional arguments
bool absentDim = isStaticallyAbsent(args[2]);
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2797,7 +2797,7 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef<fir::ExtendedValue> args) {
if (vType != targetType) {
if (mlir::isa<mlir::VectorType>(targetType)) {
// Perform vector type conversion for arguments passed by value.
auto eleTy{mlir::dyn_cast<fir::VectorType>(vType).getEleTy()};
auto eleTy{mlir::dyn_cast<fir::VectorType>(vType).getElementType()};
auto len{mlir::dyn_cast<fir::VectorType>(vType).getLen()};
mlir::VectorType mlirType = mlir::VectorType::get(len, eleTy);
auto v0{builder.createConvert(loc, mlirType, v)};
Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ struct ForcedSpacing16 {
}
};

/// Generate call to Exponent instrinsic runtime routine.
/// Generate call to Exponent intrinsic runtime routine.
mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Type resultType,
mlir::Value x) {
Expand Down Expand Up @@ -320,7 +320,7 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder,
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}

/// Generate call to Fraction instrinsic runtime routine.
/// Generate call to Fraction intrinsic runtime routine.
mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value x) {
mlir::func::FuncOp func;
Expand Down Expand Up @@ -596,7 +596,7 @@ mlir::Value fir::runtime::genSelectedRealKind(fir::FirOpBuilder &builder,
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}

/// Generate call to Set_exponent instrinsic runtime routine.
/// Generate call to Set_exponent intrinsic runtime routine.
mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value x,
mlir::Value i) {
Expand Down
26 changes: 13 additions & 13 deletions flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@ void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value back) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
fir::factory::CharacterExprHelper charHelper{builder, loc};
auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
mlir::func::FuncOp func;
Expand Down Expand Up @@ -1189,7 +1189,7 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder,
mlir::Value maskBox) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
mlir::func::FuncOp func;
Expand Down Expand Up @@ -1241,7 +1241,7 @@ void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value back) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
mlir::func::FuncOp func;
REAL_INTRINSIC_INSTANCES(Minloc, )
Expand Down Expand Up @@ -1298,7 +1298,7 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder,
mlir::Value maskBox) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);

Expand Down Expand Up @@ -1326,7 +1326,7 @@ void fir::runtime::genNorm2Dim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::func::FuncOp func;
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
if (eleTy.isF128())
func = fir::runtime::getRuntimeFunc<ForcedNorm2DimReal16>(loc, builder);
else
Expand All @@ -1348,7 +1348,7 @@ mlir::Value fir::runtime::genNorm2(fir::FirOpBuilder &builder,
mlir::func::FuncOp func;
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);

if (eleTy.isF32())
Expand Down Expand Up @@ -1398,7 +1398,7 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder,
mlir::Value resultBox) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);

auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
Expand Down Expand Up @@ -1482,7 +1482,7 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);

auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
Expand Down Expand Up @@ -1513,15 +1513,15 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,

// The IAll, IAny and IParity intrinsics have essentially the same
// implementation. This macro will generate the function body given the
// instrinsic name.
// intrinsic name.
#define GEN_IALL_IANY_IPARITY(F) \
mlir::Value fir::runtime::JOIN2(gen, F)( \
fir::FirOpBuilder & builder, mlir::Location loc, mlir::Value arrayBox, \
mlir::Value maskBox, mlir::Value resultBox) { \
mlir::func::FuncOp func; \
auto ty = arrayBox.getType(); \
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); \
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy(); \
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType(); \
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); \
\
if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) \
Expand Down Expand Up @@ -1596,7 +1596,7 @@ void fir::runtime::genReduce(fir::FirOpBuilder &builder, mlir::Location loc,
bool argByRef) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getI32Type(), 1);

assert(resultBox && "expect non null value for the result");
Expand Down Expand Up @@ -1646,7 +1646,7 @@ mlir::Value fir::runtime::genReduce(fir::FirOpBuilder &builder,
bool argByRef) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto dim = builder.createIntegerConstant(loc, builder.getI32Type(), 1);

assert((fir::isa_real(eleTy) || fir::isa_integer(eleTy) ||
Expand Down Expand Up @@ -1687,7 +1687,7 @@ void fir::runtime::genReduceDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, bool argByRef) {
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);

mlir::func::FuncOp func;
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Optimizer/Builder/Runtime/Transformational.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,11 @@ void fir::runtime::genMatmul(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::func::FuncOp func;
auto boxATy = matrixABox.getType();
auto arrATy = fir::dyn_cast_ptrOrBoxEleTy(boxATy);
auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getEleTy();
auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getElementType();
auto [aCat, aKind] = fir::mlirTypeToCategoryKind(loc, arrAEleTy);
auto boxBTy = matrixBBox.getType();
auto arrBTy = fir::dyn_cast_ptrOrBoxEleTy(boxBTy);
auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getEleTy();
auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getElementType();
auto [bCat, bKind] = fir::mlirTypeToCategoryKind(loc, arrBEleTy);

#define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND) \
Expand Down Expand Up @@ -417,11 +417,11 @@ void fir::runtime::genMatmulTranspose(fir::FirOpBuilder &builder,
mlir::func::FuncOp func;
auto boxATy = matrixABox.getType();
auto arrATy = fir::dyn_cast_ptrOrBoxEleTy(boxATy);
auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getEleTy();
auto arrAEleTy = mlir::cast<fir::SequenceType>(arrATy).getElementType();
auto [aCat, aKind] = fir::mlirTypeToCategoryKind(loc, arrAEleTy);
auto boxBTy = matrixBBox.getType();
auto arrBTy = fir::dyn_cast_ptrOrBoxEleTy(boxBTy);
auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getEleTy();
auto arrBEleTy = mlir::cast<fir::SequenceType>(arrBTy).getElementType();
auto [bCat, bKind] = fir::mlirTypeToCategoryKind(loc, arrBEleTy);

#define MATMUL_INSTANCE(ACAT, AKIND, BCAT, BKIND) \
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2619,7 +2619,7 @@ struct CoordinateOpConversion
dims = dimsLeft - 1;
continue;
}
cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getEleTy();
cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getElementType();
// append array range in reverse (FIR arrays are column-major)
offs.append(arrIdx.rbegin(), arrIdx.rend());
arrIdx.clear();
Expand All @@ -2633,7 +2633,7 @@ struct CoordinateOpConversion
arrIdx.push_back(nxtOpnd);
continue;
}
cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getEleTy();
cpnTy = mlir::cast<fir::SequenceType>(cpnTy).getElementType();
offs.push_back(nxtOpnd);
continue;
}
Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Optimizer/Dialect/FIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ bool fir::ConvertOp::isPointerCompatible(mlir::Type ty) {
static std::optional<mlir::Type> getVectorElementType(mlir::Type ty) {
mlir::Type elemTy;
if (mlir::isa<fir::VectorType>(ty))
elemTy = mlir::dyn_cast<fir::VectorType>(ty).getEleTy();
elemTy = mlir::dyn_cast<fir::VectorType>(ty).getElementType();
else if (mlir::isa<mlir::VectorType>(ty))
elemTy = mlir::dyn_cast<mlir::VectorType>(ty).getElementType();
else
Expand Down Expand Up @@ -1533,7 +1533,7 @@ llvm::LogicalResult fir::CoordinateOp::verify() {
}
if (dimension) {
if (--dimension == 0)
eleTy = mlir::cast<fir::SequenceType>(eleTy).getEleTy();
eleTy = mlir::cast<fir::SequenceType>(eleTy).getElementType();
} else {
if (auto t = mlir::dyn_cast<mlir::TupleType>(eleTy)) {
// FIXME: Generally, we don't know which field of the tuple is being
Expand Down Expand Up @@ -3817,7 +3817,7 @@ void fir::StoreOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
//===----------------------------------------------------------------------===//

inline fir::CharacterType::KindTy stringLitOpGetKind(fir::StringLitOp op) {
auto eleTy = mlir::cast<fir::SequenceType>(op.getType()).getEleTy();
auto eleTy = mlir::cast<fir::SequenceType>(op.getType()).getElementType();
return mlir::cast<fir::CharacterType>(eleTy).getFKind();
}

Expand Down
18 changes: 18 additions & 0 deletions flang/lib/Parser/parse-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,21 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
return os << x.ToString();
}
} // namespace Fortran::parser

template <typename C> static llvm::omp::Clause getClauseIdForClass(C &&) {
using namespace Fortran;
using A = llvm::remove_cvref_t<C>; // A is referenced in OMP.inc
// The code included below contains a sequence of checks like the following
// for each OpenMP clause
// if constexpr (std::is_same_v<A, parser::OmpClause::AcqRel>)
// return llvm::omp::Clause::OMPC_acq_rel;
// [...]
#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
#include "llvm/Frontend/OpenMP/OMP.inc"
}

namespace Fortran::parser {
llvm::omp::Clause OmpClause::Id() const {
return std::visit([](auto &&s) { return getClauseIdForClass(s); }, u);
}
} // namespace Fortran::parser
46 changes: 35 additions & 11 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,23 @@ class OmpWorkshareBlockChecker {
if (const auto *e{GetExpr(context_, expr)}) {
for (const Symbol &symbol : evaluate::CollectSymbols(*e)) {
const Symbol &root{GetAssociationRoot(symbol)};
if (IsFunction(root) && !IsElementalProcedure(root)) {
context_.Say(expr.source,
"User defined non-ELEMENTAL function "
"'%s' is not allowed in a WORKSHARE construct"_err_en_US,
root.name());
if (IsFunction(root)) {
std::string attrs{""};
if (!IsElementalProcedure(root)) {
attrs = " non-ELEMENTAL";
}
if (root.attrs().test(Attr::IMPURE)) {
if (attrs != "") {
attrs = "," + attrs;
}
attrs = " IMPURE" + attrs;
}
if (attrs != "") {
context_.Say(expr.source,
"User defined%s function '%s' is not allowed in a "
"WORKSHARE construct"_err_en_US,
attrs, root.name());
}
}
}
}
Expand Down Expand Up @@ -2273,6 +2285,21 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
}
}
}

// 2.11.5 Simd construct restriction (OpenMP 5.1)
if (auto *sl_clause{FindClause(llvm::omp::Clause::OMPC_safelen)}) {
if (auto *o_clause{FindClause(llvm::omp::Clause::OMPC_order)}) {
const auto &orderClause{
std::get<parser::OmpClause::Order>(o_clause->u)};
if (std::get<parser::OmpOrderClause::Type>(orderClause.v.t) ==
parser::OmpOrderClause::Type::Concurrent) {
context_.Say(sl_clause->source,
"The `SAFELEN` clause cannot appear in the `SIMD` directive "
"with `ORDER(CONCURRENT)` clause"_err_en_US);
}
}
}

// Sema checks related to presence of multiple list items within the same
// clause
CheckMultListItems();
Expand Down Expand Up @@ -2336,11 +2363,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
void OmpStructureChecker::Enter(const parser::OmpClause &x) {
SetContextClause(x);

llvm::omp::Clause clauseId = std::visit(
[this](auto &&s) { return GetClauseKindForParserClass(s); }, x.u);

// The visitors for these clauses do their own checks.
switch (clauseId) {
switch (x.Id()) {
case llvm::omp::Clause::OMPC_copyprivate:
case llvm::omp::Clause::OMPC_enter:
case llvm::omp::Clause::OMPC_lastprivate:
Expand Down Expand Up @@ -3217,7 +3241,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
DirectivesClauseTriple dirClauseTriple;
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(objectList, currSymbols);
CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x));
CheckDefinableObjects(currSymbols, llvm::omp::Clause::OMPC_lastprivate);
CheckCopyingPolymorphicAllocatable(
currSymbols, llvm::omp::Clause::OMPC_lastprivate);

Expand All @@ -3230,7 +3254,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet));

CheckPrivateSymbolsInOuterCxt(
currSymbols, dirClauseTriple, GetClauseKindForParserClass(x));
currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);

using LastprivateModifier = parser::OmpLastprivateClause::LastprivateModifier;
const auto &maybeMod{std::get<std::optional<LastprivateModifier>>(x.v.t)};
Expand Down
7 changes: 0 additions & 7 deletions flang/lib/Semantics/check-omp-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,6 @@ class OmpStructureChecker
#define GEN_FLANG_CLAUSE_CHECK_ENTER
#include "llvm/Frontend/OpenMP/OMP.inc"

// Get the OpenMP Clause Kind for the corresponding Parser class
template <typename A>
llvm::omp::Clause GetClauseKindForParserClass(const A &) {
#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
#include "llvm/Frontend/OpenMP/OMP.inc"
}

private:
bool CheckAllowedClause(llvmOmpClause clause);
bool IsVariableListItem(const Symbol &sym);
Expand Down
2 changes: 2 additions & 0 deletions flang/test/Driver/frontend-forwarding.f90
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
! RUN: -fno-signed-zeros \
! RUN: -fassociative-math \
! RUN: -freciprocal-math \
! RUN: -fno-strict-overflow \
! RUN: -fomit-frame-pointer \
! RUN: -fpass-plugin=Bye%pluginext \
! RUN: -fversion-loops-for-stride \
Expand Down Expand Up @@ -63,4 +64,5 @@
! CHECK: "-Rpass=inline"
! CHECK: "-mframe-pointer=none"
! CHECK: "-mllvm" "-print-before-all"
! CHECK: "-fwrapv"
! CHECK: "-save-temps=obj"
10 changes: 10 additions & 0 deletions flang/test/Driver/integer-overflow.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
! Test for correct forwarding of integer overflow flags from the compiler driver
! to the frontend driver

! RUN: %flang -### -fno-strict-overflow %s 2>&1 | FileCheck %s --check-prefix=INDUCED
! RUN: %flang -### -fstrict-overflow %s 2>&1 | FileCheck %s
! RUN: %flang -### -fno-wrapv %s 2>&1 | FileCheck %s
! RUN: %flang -### -fno-wrapv -fno-strict-overflow %s 2>&1 | FileCheck %s

! CHECK-NOT: "-fno-wrapv"
! INDUCED: "-fwrapv"
50 changes: 50 additions & 0 deletions flang/test/Integration/OpenMP/atomic-capture-complex.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
!===----------------------------------------------------------------------===!
! This directory can be used to add Integration tests involving multiple
! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
! contain executable tests. We should only add tests here sparingly and only
! if there is no other way to test. Repeat this message in each test that is
! added to this directory and sub-directories.
!===----------------------------------------------------------------------===!

!RUN: %if x86-registered-target %{ %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,X86 %s %}
!RUN: %if aarch64-registerd-target %{ %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fopenmp %s -o - | FileCheck --check-prefixes=CHECK,AARCH64 %s %}

!CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 8
!CHECK: %[[VAL_1:.*]] = alloca { float, float }, i64 1, align 8
!CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 8
!CHECK: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[ORIG_VAL]], align 4
!CHECK: br label %entry

!CHECK: entry:
!CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8
!CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)
!CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8
!CHECK: br label %.atomic.cont

!CHECK: .atomic.cont
!CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]
!CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 0
!CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 1
!CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+00
!CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+00
!CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 0
!CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 1
!CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4
!CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]],
!i32 2, i32 2)
!CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 4
!CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont

!CHECK: .atomic.exit
!AARCH64: %[[LCSSA:.*]] = phi { float, float } [ %[[VAL_10]], %.atomic.cont ]
!AARCH64: store { float, float } %[[LCSSA]], ptr %[[VAL_1]], align 4
!X86: store { float, float } %[[VAL_10]], ptr %[[VAL_1]], align 4

program main
complex*8 ia, ib
ia = (2, 2)
!$omp atomic capture
ia = ia + (1, 1)
ib = ia
!$omp end atomic
end program
6 changes: 6 additions & 0 deletions flang/test/Semantics/OpenMP/clause-validity01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,12 @@
enddo
!$omp end parallel

!ERROR: The `SAFELEN` clause cannot appear in the `SIMD` directive with `ORDER(CONCURRENT)` clause
!$omp simd order(concurrent) safelen(1+2)
do i = 1, N
a = 3.14
enddo

! 2.11.1 parallel-do-clause -> parallel-clause |
! do-clause

Expand Down
8 changes: 7 additions & 1 deletion flang/test/Semantics/OpenMP/do-collapse.f90
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@ program omp_doCollapse
do
end do
end do
end program omp_doCollapse

!ERROR: At most one COLLAPSE clause can appear on the SIMD directive
!$omp simd collapse(2) collapse(1)
do i = 1, 4
j = j + i + 1
end do
!$omp end simd
end program omp_doCollapse
6 changes: 6 additions & 0 deletions flang/test/Semantics/OpenMP/loop-association.f90
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,10 @@
!$omp end parallel do simd
!ERROR: The END PARALLEL DO SIMD directive must follow the DO loop associated with the loop construct
!$omp end parallel do simd

!ERROR: A DO loop must follow the SIMD directive
!$omp simd
a = i + 1
!ERROR: The END SIMD directive must follow the DO loop associated with the loop construct
!$omp end simd
end
18 changes: 18 additions & 0 deletions flang/test/Semantics/OpenMP/workshare02.f90
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ module my_mod
integer function my_func()
my_func = 10
end function my_func

impure integer function impure_my_func()
impure_my_func = 20
end function impure_my_func

impure elemental integer function impure_ele_my_func()
impure_ele_my_func = 20
end function impure_ele_my_func
end module my_mod

subroutine workshare(aa, bb, cc, dd, ee, ff, n)
Expand Down Expand Up @@ -61,6 +69,16 @@ subroutine workshare(aa, bb, cc, dd, ee, ff, n)
j = j - my_func()
!$omp end atomic

!ERROR: User defined IMPURE, non-ELEMENTAL function 'impure_my_func' is not allowed in a WORKSHARE construct
cc = impure_my_func()
!ERROR: User defined IMPURE function 'impure_ele_my_func' is not allowed in a WORKSHARE construct
aa(1) = impure_ele_my_func()

!$omp end workshare

!$omp workshare
j = j + 1
!ERROR: At most one NOWAIT clause can appear on the END WORKSHARE directive
!$omp end workshare nowait nowait

end subroutine workshare
11 changes: 8 additions & 3 deletions libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ function(_get_compile_options_from_config output_var)
list(APPEND config_options "-DLIBC_ADD_NULL_CHECKS")
endif()

if(NOT "${LIBC_CONF_FREXP_INF_NAN_EXPONENT}" STREQUAL "")
list(APPEND config_options "-DLIBC_FREXP_INF_NAN_EXPONENT=${LIBC_CONF_FREXP_INF_NAN_EXPONENT}")
endif()

if(LIBC_CONF_MATH_OPTIMIZATIONS)
list(APPEND compile_options "-DLIBC_MATH=${LIBC_CONF_MATH_OPTIMIZATIONS}")
endif()

set(${output_var} ${config_options} PARENT_SCOPE)
endfunction(_get_compile_options_from_config)

Expand Down Expand Up @@ -170,9 +178,6 @@ function(_get_common_compile_options output_var flags)
list(APPEND compile_options "-Wthread-safety")
list(APPEND compile_options "-Wglobal-constructors")
endif()
if(LIBC_CONF_MATH_OPTIMIZATIONS)
list(APPEND compile_options "-DLIBC_MATH=${LIBC_CONF_MATH_OPTIMIZATIONS}")
endif()
elseif(MSVC)
list(APPEND compile_options "/EHs-c-")
list(APPEND compile_options "/GR-")
Expand Down
4 changes: 4 additions & 0 deletions libc/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@
"LIBC_CONF_MATH_OPTIMIZATIONS": {
"value": 0,
"doc": "Configures optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, and LIBC_MATH_FAST."
},
"LIBC_CONF_FREXP_INF_NAN_EXPONENT": {
"value": "",
"doc": "The value written back to the second parameter when calling frexp/frexpf/frexpl` with `+/-Inf`/`NaN` is unspecified. Configue an explicit exp value for Inf/NaN inputs."
}
},
"qsort": {
Expand Down
1 change: 1 addition & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.setpayloadf16
libc.src.math.setpayloadsigf16
libc.src.math.sinhf16
libc.src.math.tanhf16
libc.src.math.totalorderf16
libc.src.math.totalordermagf16
libc.src.math.truncf16
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.setpayloadsigf16
libc.src.math.sinhf16
libc.src.math.sinpif16
libc.src.math.tanhf16
libc.src.math.totalorderf16
libc.src.math.totalordermagf16
libc.src.math.truncf16
Expand Down
1 change: 1 addition & 0 deletions libc/docs/configure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ to learn about the defaults for your platform and target.
* **"general" options**
- ``LIBC_ADD_NULL_CHECKS``: Add nullptr checks in the library's implementations to some functions for which passing nullptr is undefined behavior.
* **"math" options**
- ``LIBC_CONF_FREXP_INF_NAN_EXPONENT``: The value written back to the second parameter when calling frexp/frexpf/frexpl` with `+/-Inf`/`NaN` is unspecified. Configue an explicit exp value for Inf/NaN inputs.
- ``LIBC_CONF_MATH_OPTIMIZATIONS``: Configures optimizations for math functions. Values accepted are LIBC_MATH_SKIP_ACCURATE_PASS, LIBC_MATH_SMALL_TABLES, LIBC_MATH_NO_ERRNO, LIBC_MATH_NO_EXCEPT, and LIBC_MATH_FAST.
* **"printf" options**
- ``LIBC_CONF_PRINTF_DISABLE_FIXED_POINT``: Disable printing fixed point values in printf and friends.
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| tan | |check| | |check| | | | | 7.12.4.7 | F.10.1.7 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| tanh | |check| | | | | | 7.12.5.6 | F.10.2.6 |
| tanh | |check| | | | |check| | | 7.12.5.6 | F.10.2.6 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| tanpi | | | | | | 7.12.4.14 | F.10.1.14 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down
8 changes: 8 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ add_header(
DEPENDS
libc.include.llvm-libc-macros.float_macros
)
add_header(
cfloat128
HDR
cfloat128.h
DEPENDS
libc.include.llvm-libc-macros.float_macros
)
add_header(cfloat16 HDR cfloat16.h)
add_header(fsblkcnt_t HDR fsblkcnt_t.h)
add_header(fsfilcnt_t HDR fsfilcnt_t.h)
add_header(
Expand Down
41 changes: 41 additions & 0 deletions libc/include/llvm-libc-types/cfloat128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===-- Definition of cfloat128 type --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_TYPES_CFLOAT128_H
#define LLVM_LIBC_TYPES_CFLOAT128_H

#include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG

// Currently, the complex variant of C23 `_Float128` type is only defined as a
// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For
// clang, the complex variant of `__float128` is defined instead, and only on
// x86-64 targets for clang 11 or later.
//
// TODO: Update the complex variant of C23 `_Float128` type detection again when
// clang supports it.
#if defined(__STDC_IEC_60559_COMPLEX__) && !defined(__clang__)
#if !defined(__cplusplus)
#define LIBC_TYPES_HAS_CFLOAT128
typedef _Complex _Float128 cfloat128;
#elif defined(__GNUC__) && __GNUC__ >= 13
#define LIBC_TYPES_HAS_CFLOAT128
typedef _Complex _Float128 cfloat128;
#endif
#elif __clang_major__ >= 11 && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__
// macro to notify the availability of __float128 type:
// https://reviews.llvm.org/D15120
#define LIBC_TYPES_HAS_CFLOAT128
typedef _Complex __float128 cfloat128;
#elif (LDBL_MANT_DIG == 113)
#define LIBC_TYPES_HAS_CFLOAT128
typedef _Complex long double cfloat128;
#endif

#endif // LLVM_LIBC_TYPES_CFLOAT128_H
21 changes: 21 additions & 0 deletions libc/include/llvm-libc-types/cfloat16.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Definition of cfloat16 type ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_TYPES_CFLOAT16_H
#define LLVM_LIBC_TYPES_CFLOAT16_H

#if defined(__FLT16_MANT_DIG__) && \
(!defined(__GNUC__) || __GNUC__ >= 13 || \
(defined(__clang__) && __clang_major__ >= 14)) && \
!defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
!defined(_WIN32)
#define LIBC_TYPES_HAS_CFLOAT16
typedef _Complex _Float16 cfloat16;
#endif

#endif // LLVM_LIBC_TYPES_CFLOAT16_H
1 change: 1 addition & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ def StdC : StandardSpec<"stdc"> {
GuardedFunctionSpec<"sinhf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

FunctionSpec<"tanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
GuardedFunctionSpec<"tanhf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

FunctionSpec<"acosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,

Expand Down
2 changes: 2 additions & 0 deletions libc/src/__support/CPP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ add_header_library(
type_traits/is_array.h
type_traits/is_base_of.h
type_traits/is_class.h
type_traits/is_complex.h
type_traits/is_const.h
type_traits/is_constant_evaluated.h
type_traits/is_convertible.h
Expand Down Expand Up @@ -165,6 +166,7 @@ add_header_library(
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
libc.src.__support.macros.properties.types
libc.src.__support.macros.properties.complex_types
)

add_header_library(
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/CPP/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "src/__support/CPP/type_traits/is_array.h"
#include "src/__support/CPP/type_traits/is_base_of.h"
#include "src/__support/CPP/type_traits/is_class.h"
#include "src/__support/CPP/type_traits/is_complex.h"
#include "src/__support/CPP/type_traits/is_const.h"
#include "src/__support/CPP/type_traits/is_constant_evaluated.h"
#include "src/__support/CPP/type_traits/is_convertible.h"
Expand Down
15 changes: 14 additions & 1 deletion libc/src/__support/CPP/type_traits/is_complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

#include "src/__support/CPP/type_traits/is_same.h"
#include "src/__support/CPP/type_traits/remove_cv.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
// LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128
#include "src/__support/macros/properties/complex_types.h"

namespace LIBC_NAMESPACE_DECL {
namespace cpp {
Expand All @@ -25,7 +29,16 @@ template <typename T> struct is_complex {
public:
LIBC_INLINE_VAR static constexpr bool value =
__is_unqualified_any_of<T, _Complex float, _Complex double,
_Complex long double>();
_Complex long double
#ifdef LIBC_TYPES_HAS_CFLOAT16
,
cfloat16
#endif
#ifdef LIBC_TYPES_HAS_CFLOAT128
,
cfloat128
#endif
>();
};
template <typename T>
LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value;
Expand Down
10 changes: 9 additions & 1 deletion libc/src/__support/FPUtil/ManipulationFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@ namespace fputil {
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T frexp(T x, int &exp) {
FPBits<T> bits(x);
if (bits.is_inf_or_nan())
if (bits.is_inf_or_nan()) {
#ifdef LIBC_FREXP_INF_NAN_EXPONENT
// The value written back to the second parameter when calling
// frexp/frexpf/frexpl` with `+/-Inf`/`NaN` is unspecified in the standard.
// Set the exp value for Inf/NaN inputs explicitly to
// LIBC_FREXP_INF_NAN_EXPONENT if it is defined.
exp = LIBC_FREXP_INF_NAN_EXPONENT;
#endif // LIBC_FREXP_INF_NAN_EXPONENT
return x;
}
if (bits.is_zero()) {
exp = 0;
return x;
Expand Down
10 changes: 10 additions & 0 deletions libc/src/__support/macros/properties/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ add_header_library(
libc.include.llvm-libc-macros.float16_macros
libc.include.llvm-libc-types.float128
)

add_header_library(
complex_types
HDRS
complex_types.h
DEPENDS
.types
libc.include.llvm-libc-types.cfloat16
libc.include.llvm-libc-types.cfloat128
)
25 changes: 25 additions & 0 deletions libc/src/__support/macros/properties/complex_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===-- Complex Types support -----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Complex Types detection and support.

#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H

#include "include/llvm-libc-types/cfloat128.h"
#include "include/llvm-libc-types/cfloat16.h"
#include "types.h"

// -- cfloat16 support --------------------------------------------------------
// LIBC_TYPES_HAS_CFLOAT16 and 'cfloat16' type is provided by
// "include/llvm-libc-types/cfloat16.h"

// -- cfloat128 support -------------------------------------------------------
// LIBC_TYPES_HAS_CFLOAT128 and 'cfloat128' type are provided by
// "include/llvm-libc-types/cfloat128.h"

#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
1 change: 1 addition & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ add_math_entrypoint_object(tanf)

add_math_entrypoint_object(tanh)
add_math_entrypoint_object(tanhf)
add_math_entrypoint_object(tanhf16)

add_math_entrypoint_object(tgamma)
add_math_entrypoint_object(tgammaf)
Expand Down
23 changes: 23 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4288,6 +4288,29 @@ add_entrypoint_object(
-O3
)

add_entrypoint_object(
tanhf16
SRCS
tanhf16.cpp
HDRS
../tanhf16.h
DEPENDS
.expxf16
libc.hdr.fenv_macros
libc.src.__support.CPP.array
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.nearest_integer
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.optimization
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
acoshf
SRCS
Expand Down
2 changes: 1 addition & 1 deletion libc/src/math/generic/exp10f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {

// 10^x = 2^((hi + mid) * log2(10)) * 10^lo
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
return static_cast<float16>(exp2_hi_mid * exp10_lo);
return fputil::cast<float16>(exp2_hi_mid * exp10_lo);
}

} // namespace LIBC_NAMESPACE_DECL
6 changes: 3 additions & 3 deletions libc/src/math/generic/powf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,9 +855,9 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
: 0.0;
exp2_hi_mid_dd.hi = exp2_hi_mid;

return static_cast<float>(
powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd)) +
0.0f;
double r_dd = powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd);

return static_cast<float>(r_dd);
}

} // namespace LIBC_NAMESPACE_DECL
144 changes: 144 additions & 0 deletions libc/src/math/generic/tanhf16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//===-- Half-precision tanh(x) function -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/math/tanhf16.h"
#include "expxf16.h"
#include "hdr/fenv_macros.h"
#include "src/__support/CPP/array.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"

namespace LIBC_NAMESPACE_DECL {

static constexpr fputil::ExceptValues<float16, 2> TANHF16_EXCEPTS = {{
// x = 0x1.f54p+0, tanhf16(x) = 0x1.ecp-1 (RZ)
{0x3fd5U, 0x3bb0U, 1U, 0U, 0U},
// x = -0x1.f54p+0, tanhf16(x) = -0x1.ecp-1 (RZ)
{0xbfd5U, 0xbbb0U, 0U, 1U, 0U},
}};

LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
FPBits x_bits(x);

uint16_t x_u = x_bits.uintval();
uint16_t x_abs = x_u & 0x7fffU;

// When -2^(-14) <= x <= -2^(-9), or |x| <= 0x1.d2p-4,
// or |x| >= atanh(1 - 2^(-11)), or x is NaN.
if (LIBC_UNLIKELY(x_abs <= 0x2f48U || x_abs >= 0x4429U)) {
// tanh(NaN) = NaN
if (x_bits.is_nan()) {
if (x_bits.is_signaling_nan()) {
fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
}

return x;
}

// When -2^(-14) <= x <= -2^(-9).
if (x_u >= 0x8400U && x_u <= 0x9800U) {
switch (fputil::quick_get_round()) {
case FE_TONEAREST:
case FE_DOWNWARD:
return x;
default:
return FPBits(static_cast<uint16_t>(x_u - 1U)).get_val();
}
}

// When |x| <= 0x1.d2p-4.
if (x_abs <= 0x2f48U) {
float xf = x;
float xf_sq = xf * xf;
// Degree-7 Taylor expansion generated by Sollya with the following
// commands:
// > taylor(tanh(x), 7, 0);
// > display = hexadecimal;
// > // For each coefficient:
// > round(/* put coefficient here */, SG, RN);
return fputil::cast<float16>(
xf * fputil::polyeval(xf_sq, 0x1p+0f, -0x1.555556p-2f, 0x1.111112p-3f,
-0x1.ba1ba2p-5f));
}

// tanh(+/-inf) = +/-1
if (x_bits.is_inf())
return FPBits::one(x_bits.sign()).get_val();

// When |x| >= atanh(1 - 2^(-11)).
fputil::raise_except_if_required(FE_INEXACT);

int rounding_mode = fputil::quick_get_round();
if ((rounding_mode == FE_TONEAREST && x_abs >= 0x4482U) ||
(rounding_mode == FE_UPWARD && x_bits.is_pos()) ||
(rounding_mode == FE_DOWNWARD && x_bits.is_neg())) {
return FPBits::one(x_bits.sign()).get_val();
}
if (x_bits.is_pos())
return fputil::cast<float16>(0x1.ffcp-1);
return fputil::cast<float16>(-0x1.ffcp-1);
}

if (auto r = TANHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();

// For atanh(-1 + 2^(-11)) < x < atanh(1 - 2^(-11)), to compute tanh(x), we
// perform the following range reduction: find hi, mid, lo, such that:
// x = (hi + mid) * log(2) * 0.5 + lo, in which
// hi is an integer,
// mid * 2^5 is an integer,
// -2^(-5) <= lo < 2^(-5).
// In particular,
// hi + mid = round(x * log2(e) * 2 * 2^5) * 2^(-5).
// Then,
// tanh(x) = sinh(x)/cosh(x)
// = (e^x - e^(-x)) / (e^x + e^(-x))
// = (e^(2x) - 1) / (e^(2x) + 1)
// = (2^(hi + mid) * e^(2*lo) - 1) / (2^(hi + mid) * e^(2*lo) + 1)
// = (e^(2*lo) - 2^(-hi - mid)) / (e^(2*lo) + 2^(-hi - mid))
// We store 2^(-mid) in the lookup table EXP2_MID_5_BITS, and compute
// 2^(-hi - mid) by adding -hi to the exponent field of 2^(-mid).
// e^lo is computed using a degree-3 minimax polynomial generated by Sollya.

float xf = x;
float kf = fputil::nearest_integer(xf * (LOG2F_E * 2.0f * 0x1.0p+5f));
int x_hi_mid = -static_cast<int>(kf);
unsigned x_hi = static_cast<unsigned>(x_hi_mid) >> 5;
unsigned x_mid = static_cast<unsigned>(x_hi_mid) & 0x1f;
// lo = x - (hi + mid)
// = round(x * log2(e) * 2 * 2^5) * log(2) * 0.5 * (-2^(-5)) + x
float lo = fputil::multiply_add(kf, LOGF_2 * 0.5f * -0x1.0p-5f, xf);

uint32_t exp2_hi_mid_bits =
EXP2_MID_5_BITS[x_mid] +
static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN);
// exp2_hi_mid = 2^(-hi - mid)
float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val();
// Degree-3 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax(expm1(2*x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
// > 1 + x * P;
float exp_2lo =
fputil::polyeval(lo, 0x1p+0f, 0x1p+1f, 0x1.001p+1f, 0x1.555ddep+0f);
return fputil::cast<float16>((exp_2lo - exp2_hi_mid) /
(exp_2lo + exp2_hi_mid));
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 21 additions & 0 deletions libc/src/math/tanhf16.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for tanhf16 -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_MATH_TANHF16_H
#define LLVM_LIBC_SRC_MATH_TANHF16_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 tanhf16(float16 x);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_TANHF16_H
17 changes: 17 additions & 0 deletions libc/test/UnitTest/FPMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "src/__support/CPP/array.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/CPP/type_traits/is_complex.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/fpbits_str.h"
Expand Down Expand Up @@ -128,6 +129,14 @@ template <typename T, TestCond Condition> class CFPMatcher : public Matcher<T> {
return matchComplex<double>();
else if (cpp::is_complex_type_same<T, _Complex long double>())
return matchComplex<long double>();
#ifdef LIBC_TYPES_HAS_CFLOAT16
else if (cpp::is_complex_type_same<T, cfloat16>)
return matchComplex<float16>();
#endif
#ifdef LIBC_TYPES_HAS_CFLOAT128
else if (cpp::is_complex_type_same<T, cfloat128>)
return matchComplex<float128>();
#endif
}

void explainError() override {
Expand All @@ -137,6 +146,14 @@ template <typename T, TestCond Condition> class CFPMatcher : public Matcher<T> {
return explainErrorComplex<double>();
else if (cpp::is_complex_type_same<T, _Complex long double>())
return explainErrorComplex<long double>();
#ifdef LIBC_TYPES_HAS_CFLOAT16
else if (cpp::is_complex_type_same<T, cfloat16>)
return explainErrorComplex<float16>();
#endif
#ifdef LIBC_TYPES_HAS_CFLOAT128
else if (cpp::is_complex_type_same<T, cfloat128>)
return explainErrorComplex<float128>();
#endif
}
};

Expand Down
11 changes: 11 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,17 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
tanhf16_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
tanhf16_test.cpp
DEPENDS
libc.src.math.tanhf16
)

add_fp_unittest(
atanhf_test
NEED_MPFR
Expand Down
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3778,6 +3778,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
tanhf16_test
SUITE
libc-math-smoke-tests
SRCS
tanhf16_test.cpp
DEPENDS
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.tanhf16
libc.src.__support.FPUtil.cast
)

add_fp_unittest(
atanhf_test
SUITE
Expand Down
11 changes: 11 additions & 0 deletions libc/test/src/math/smoke/FrexpTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,19 @@ class FrexpTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
void testSpecialNumbers(FrexpFunc func) {
int exponent;
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(aNaN, &exponent));
#ifdef LIBC_FREXP_INF_NAN_EXPONENT
EXPECT_EQ(LIBC_FREXP_INF_NAN_EXPONENT, exponent);
#endif // LIBC_FREXP_INF_NAN_EXPONENT

EXPECT_FP_EQ_ALL_ROUNDING(inf, func(inf, &exponent));
#ifdef LIBC_FREXP_INF_NAN_EXPONENT
EXPECT_EQ(LIBC_FREXP_INF_NAN_EXPONENT, exponent);
#endif // LIBC_FREXP_INF_NAN_EXPONENT

EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf, &exponent));
#ifdef LIBC_FREXP_INF_NAN_EXPONENT
EXPECT_EQ(LIBC_FREXP_INF_NAN_EXPONENT, exponent);
#endif // LIBC_FREXP_INF_NAN_EXPONENT

EXPECT_FP_EQ_ALL_ROUNDING(zero, func(zero, &exponent));
EXPECT_EQ(exponent, 0);
Expand Down
3 changes: 3 additions & 0 deletions libc/test/src/math/smoke/powf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,7 @@ TEST_F(LlvmLibcPowfTest, SpecialNumbers) {
FE_UNDERFLOW);
}
}

EXPECT_FP_EQ(-0.0f, LIBC_NAMESPACE::powf(-0.015625f, 25.0f));
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::powf(-0.015625f, 26.0f));
}
Loading