diff options
Diffstat (limited to 'test/CodeGenCXX')
131 files changed, 4610 insertions, 457 deletions
diff --git a/test/CodeGenCXX/Inputs/override-layout-packed-base.layout b/test/CodeGenCXX/Inputs/override-layout-packed-base.layout index 949215ab849d..2ebcb98819b7 100644 --- a/test/CodeGenCXX/Inputs/override-layout-packed-base.layout +++ b/test/CodeGenCXX/Inputs/override-layout-packed-base.layout @@ -3,16 +3,26 @@ Type: class B<0> Layout: <ASTRecordLayout + Size:40 FieldOffsets: [0, 32]> *** Dumping AST Record Layout Type: class B<1> Layout: <ASTRecordLayout + Size:40 FieldOffsets: [0, 32]> *** Dumping AST Record Layout Type: class C Layout: <ASTRecordLayout + Size:88 FieldOffsets: [80]> + +*** Dumping AST Record Layout +Type: class D + +Layout: <ASTRecordLayout + Size:120 + FieldOffsets: [32]> diff --git a/test/CodeGenCXX/Inputs/profile-remap.map b/test/CodeGenCXX/Inputs/profile-remap.map new file mode 100644 index 000000000000..50b812a9165e --- /dev/null +++ b/test/CodeGenCXX/Inputs/profile-remap.map @@ -0,0 +1,2 @@ +name 3Foo 3Bar +type N3Foo1XE N3Baz1YE diff --git a/test/CodeGenCXX/Inputs/profile-remap.proftext b/test/CodeGenCXX/Inputs/profile-remap.proftext new file mode 100644 index 000000000000..a1f90cfa6e9e --- /dev/null +++ b/test/CodeGenCXX/Inputs/profile-remap.proftext @@ -0,0 +1,7 @@ +:ir +_ZN3Foo8functionENS_1XE +29667547796 +2 +10 +90 + diff --git a/test/CodeGenCXX/Inputs/profile-remap.samples b/test/CodeGenCXX/Inputs/profile-remap.samples new file mode 100644 index 000000000000..45e599470cc5 --- /dev/null +++ b/test/CodeGenCXX/Inputs/profile-remap.samples @@ -0,0 +1,3 @@ +_ZN3Bar8functionEN3Baz1YE:100:0 + 2: 10 + 4: 90 diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp index 095705f389bf..195e4e521240 100644 --- a/test/CodeGenCXX/PR20038.cpp +++ b/test/CodeGenCXX/PR20038.cpp @@ -6,9 +6,9 @@ struct C { extern bool b; // CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]] // CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]] -// CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} isDefinition: true +// CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} DISPFlagDefinition // CHECK: [[DTOR_CALL1_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN1]]) void fun1() { b && (C(), 1); } -// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} isDefinition: true +// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} DISPFlagDefinition // CHECK: [[DTOR_CALL2_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN2]]) bool fun2() { return (C(), b) && 0; } diff --git a/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp b/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp new file mode 100644 index 000000000000..3971c22287f9 --- /dev/null +++ b/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp @@ -0,0 +1,41 @@ +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY + +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=none %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=standard %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY --check-prefix=CHECK-BTE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-B-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=bti %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf+bti %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY --check-prefix=BTE + +struct Foo { + Foo() {} + ~Foo() {} +}; + +Foo f; + +// CHECK: @llvm.global_ctors {{.*}}i32 65535, void ()* @[[CTOR_FN:.*]], i8* null + +// CHECK: @[[CTOR_FN]]() #[[ATTR:[0-9]*]] + +// CHECK-NONE-NOT: "sign-return-address"={{.*}} +// CHECK-PARTIAL: "sign-return-address"="non-leaf" +// CHECK-ALL: "sign-return-address"="all" +// CHECK-A-KEY: "sign-return-address-key"="a_key" +// CHECK-B-KEY: "sign-return-address-key"="b_key" +// CHECK-BTE: "branch-target-enforcement" diff --git a/test/CodeGenCXX/address-space-cast-coerce.cpp b/test/CodeGenCXX/address-space-cast-coerce.cpp new file mode 100644 index 000000000000..940a4f55b47a --- /dev/null +++ b/test/CodeGenCXX/address-space-cast-coerce.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s + +template<typename T, unsigned int n> struct my_vector_base; + + template<typename T> + struct my_vector_base<T, 1> { + typedef T Native_vec_ __attribute__((ext_vector_type(1))); + + union { + Native_vec_ data; + struct { + T x; + }; + }; + }; + + template<typename T, unsigned int rank> + struct my_vector_type : public my_vector_base<T, rank> { + using my_vector_base<T, rank>::data; + using typename my_vector_base<T, rank>::Native_vec_; + + template< typename U> + my_vector_type(U x) noexcept + { + for (auto i = 0u; i != rank; ++i) data[i] = x; + } + my_vector_type& operator+=(const my_vector_type& x) noexcept + { + data += x.data; + return *this; + } + }; + +template<typename T, unsigned int n> + inline + my_vector_type<T, n> operator+( + const my_vector_type<T, n>& x, const my_vector_type<T, n>& y) noexcept + { + return my_vector_type<T, n>{x} += y; + } + +using char1 = my_vector_type<char, 1>; + +int mane() { + + char1 f1{1}; + char1 f2{1}; + +// CHECK: %[[a:[^ ]+]] = addrspacecast i16 addrspace(5)* %{{[^ ]+}} to i16* +// CHECK: %[[a:[^ ]+]] = addrspacecast %{{[^ ]+}} addrspace(5)* %{{[^ ]+}} to %{{[^ ]+}} + + char1 f3 = f1 + f2; +} diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp index 334a1a63e627..e0cf3c199b88 100644 --- a/test/CodeGenCXX/address-space-cast.cpp +++ b/test/CodeGenCXX/address-space-cast.cpp @@ -3,13 +3,63 @@ #define __private__ __attribute__((address_space(5))) void func_pchar(__private__ char *x); +void func_pvoid(__private__ void *x); +void func_pint(__private__ int *x); -void test_cast(char *gen_ptr) { +void test_cast(char *gen_char_ptr, void *gen_void_ptr, int *gen_int_ptr) { // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] - __private__ char *priv_ptr = (__private__ char *)gen_ptr; + __private__ char *priv_char_ptr = (__private__ char *)gen_char_ptr; // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + priv_char_ptr = (__private__ char *)gen_void_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + priv_char_ptr = (__private__ char *)gen_int_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + __private__ void *priv_void_ptr = (__private__ void *)gen_char_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + priv_void_ptr = (__private__ void *)gen_void_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + priv_void_ptr = (__private__ void *)gen_int_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)* + // CHECK-NEXT: store i32 addrspace(5)* %[[cast]] + __private__ int *priv_int_ptr = (__private__ int *)gen_void_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]]) + func_pchar((__private__ char *)gen_char_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]]) + func_pchar((__private__ char *)gen_void_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)* // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]]) - func_pchar((__private__ char *)gen_ptr); + func_pchar((__private__ char *)gen_int_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]]) + func_pvoid((__private__ void *)gen_char_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]]) + func_pvoid((__private__ void *)gen_void_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]]) + func_pvoid((__private__ void *)gen_int_ptr); + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)* + // CHECK-NEXT: call void @_Z9func_pintPU3AS5i(i32 addrspace(5)* %[[cast]]) + func_pint((__private__ int *)gen_void_ptr); } diff --git a/test/CodeGenCXX/always_destroy.cpp b/test/CodeGenCXX/always_destroy.cpp new file mode 100644 index 000000000000..e84c4cf02c52 --- /dev/null +++ b/test/CodeGenCXX/always_destroy.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 %s -fno-c++-static-destructors -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s + +struct NonTrivial { + ~NonTrivial(); +}; + +// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev +NonTrivial nt1; +// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev +thread_local NonTrivial nt2; + +struct NonTrivial2 { + ~NonTrivial2(); +}; + +// CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev +[[clang::always_destroy]] NonTrivial2 nt21; +// CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev +[[clang::always_destroy]] thread_local NonTrivial2 nt22; + +void f() { + // CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev + [[clang::always_destroy]] static NonTrivial2 nt21; + // CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev + [[clang::always_destroy]] thread_local NonTrivial2 nt22; +} + +// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::no_destroy]] NonTrivial nt3; +// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::no_destroy]] thread_local NonTrivial nt4; diff --git a/test/CodeGenCXX/amdgcn-string-literal.cpp b/test/CodeGenCXX/amdgcn-string-literal.cpp index 7fd05351c863..70be249433fb 100644 --- a/test/CodeGenCXX/amdgcn-string-literal.cpp +++ b/test/CodeGenCXX/amdgcn-string-literal.cpp @@ -4,7 +4,7 @@ // CHECK: @g_str = addrspace(1) global i8* addrspacecast (i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0) to i8*), align 8 // CHECK: @g_array = addrspace(1) global [8 x i8] c"g_array\00", align 1 // CHECK: @.str.1 = private unnamed_addr addrspace(4) constant [6 x i8] c"l_str\00", align 1 -// CHECK: @_ZZ1fvE7l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1 +// CHECK: @__const._Z1fv.l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1 const char* g_str = "g_str"; char g_array[] = "g_array"; diff --git a/test/CodeGenCXX/atomic-inline.cpp b/test/CodeGenCXX/atomic-inline.cpp index 327f85d5667f..fe727589d2e2 100644 --- a/test/CodeGenCXX/atomic-inline.cpp +++ b/test/CodeGenCXX/atomic-inline.cpp @@ -1,52 +1,6 @@ // RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s // RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu -target-cpu core2 | FileCheck %s --check-prefix=CORE2 -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i386 | FileCheck %s --check-prefix=I386 -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i486 | FileCheck %s --check-prefix=I486 -// Check the atomic code generation for cpu targets w/wo cx, cx8 and cx16 support. - -struct alignas(4) AM4 { - short f1, f2; -}; -AM4 m4; -AM4 load4() { - AM4 am; - // CHECK-LABEL: @_Z5load4v - // CHECK: load atomic i32, {{.*}} monotonic - // CORE2-LABEL: @_Z5load4v - // CORE2: load atomic i32, {{.*}} monotonic - // I386-LABEL: @_Z5load4v - // I386: call i32 @__atomic_load_4 - // I486-LABEL: @_Z5load4v - // I486: load atomic i32, {{.*}} monotonic - __atomic_load(&m4, &am, 0); - return am; -} - -AM4 s4; -void store4() { - // CHECK-LABEL: @_Z6store4v - // CHECK: store atomic i32 {{.*}} monotonic - // CORE2-LABEL: @_Z6store4v - // CORE2: store atomic i32 {{.*}} monotonic - // I386-LABEL: @_Z6store4v - // I386: call void @__atomic_store_4 - // I486-LABEL: @_Z6store4v - // I486: store atomic i32 {{.*}} monotonic - __atomic_store(&m4, &s4, 0); -} - -bool cmpxchg4() { - AM4 am; - // CHECK-LABEL: @_Z8cmpxchg4v - // CHECK: cmpxchg i32* {{.*}} monotonic - // CORE2-LABEL: @_Z8cmpxchg4v - // CORE2: cmpxchg i32* {{.*}} monotonic - // I386-LABEL: @_Z8cmpxchg4v - // I386: call zeroext i1 @__atomic_compare_exchange_4 - // I486-LABEL: @_Z8cmpxchg4v - // I486: cmpxchg i32* {{.*}} monotonic - return __atomic_compare_exchange(&m4, &s4, &am, 0, 0, 0); -} +// Check the atomic code generation for cpu targets w/wo cx16 support. struct alignas(8) AM8 { int f1, f2; @@ -58,10 +12,6 @@ AM8 load8() { // CHECK: load atomic i64, {{.*}} monotonic // CORE2-LABEL: @_Z5load8v // CORE2: load atomic i64, {{.*}} monotonic - // I386-LABEL: @_Z5load8v - // I386: call i64 @__atomic_load_8 - // I486-LABEL: @_Z5load8v - // I486: call i64 @__atomic_load_8 __atomic_load(&m8, &am, 0); return am; } @@ -72,10 +22,6 @@ void store8() { // CHECK: store atomic i64 {{.*}} monotonic // CORE2-LABEL: @_Z6store8v // CORE2: store atomic i64 {{.*}} monotonic - // I386-LABEL: @_Z6store8v - // I386: call void @__atomic_store_8 - // I486-LABEL: @_Z6store8v - // I486: call void @__atomic_store_8 __atomic_store(&m8, &s8, 0); } @@ -85,10 +31,6 @@ bool cmpxchg8() { // CHECK: cmpxchg i64* {{.*}} monotonic // CORE2-LABEL: @_Z8cmpxchg8v // CORE2: cmpxchg i64* {{.*}} monotonic - // I386-LABEL: @_Z8cmpxchg8v - // I386: call zeroext i1 @__atomic_compare_exchange_8 - // I486-LABEL: @_Z8cmpxchg8v - // I486: call zeroext i1 @__atomic_compare_exchange_8 return __atomic_compare_exchange(&m8, &s8, &am, 0, 0, 0); } @@ -124,3 +66,4 @@ bool cmpxchg16() { // CORE2: cmpxchg i128* {{.*}} monotonic return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0); } + diff --git a/test/CodeGenCXX/attr-cpuspecific.cpp b/test/CodeGenCXX/attr-cpuspecific.cpp new file mode 100644 index 000000000000..bfee49ca34bd --- /dev/null +++ b/test/CodeGenCXX/attr-cpuspecific.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX +// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS + +struct S { + __attribute__((cpu_specific(atom))) + void Func(){} + __attribute__((cpu_dispatch(ivybridge,atom))) + void Func(){} +}; + +void foo() { + S s; + s.Func(); +} + +// LINUX: define void (%struct.S*)* @_ZN1S4FuncEv.resolver +// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.S +// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.O +// LINUX: declare void @_ZN1S4FuncEv.S +// LINUX: define linkonce_odr void @_ZN1S4FuncEv.O + +// WINDOWS: define dso_local void @"?Func@S@@QEAAXXZ"(%struct.S*) +// WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.S"(%struct.S* %0) +// WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.O"(%struct.S* %0) +// WINDOWS: declare dso_local void @"?Func@S@@QEAAXXZ.S" +// WINDOWS: define linkonce_odr dso_local void @"?Func@S@@QEAAXXZ.O" diff --git a/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp b/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp new file mode 100644 index 000000000000..efbbb0cd6400 --- /dev/null +++ b/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -O0 -o - %s | FileCheck %s + +// Test that we do not assume that entities marked with the +// exclude_from_explicit_instantiation attribute are instantiated +// in another TU when an extern template instantiation declaration +// is present. We test that by making sure that definitions are +// generated in this TU despite there being an extern template +// instantiation declaration, which is normally not the case. + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) + +template <class T> +struct Foo { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1(); + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1(); + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; + + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 { + static void static_member_function() { } + }; + + struct member_class2 { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { } + }; +}; + +template <class T> inline void Foo<T>::non_static_member_function1() { } +template <class T> void Foo<T>::non_static_member_function2() { } + +template <class T> inline void Foo<T>::static_member_function1() { } +template <class T> void Foo<T>::static_member_function2() { } + +template <class T> int Foo<T>::static_data_member = 0; + +extern template struct Foo<int>; + +void use() { + Foo<int> f; + + // An inline non-static member function marked with the attribute is not + // part of the extern template declaration, so a definition must be emitted + // in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function1Ev + f.non_static_member_function1(); + + // A non-inline non-static member function marked with the attribute is + // not part of the extern template declaration, so a definition must be + // emitted in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function2Ev + f.non_static_member_function2(); + + // An inline static member function marked with the attribute is not + // part of the extern template declaration, so a definition must be + // emitted in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function1Ev + Foo<int>::static_member_function1(); + + // A non-inline static member function marked with the attribute is not + // part of the extern template declaration, so a definition must be + // emitted in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function2Ev + Foo<int>::static_member_function2(); + + // A static data member marked with the attribute is not part of the + // extern template declaration, so a definition must be emitted in this TU. + // CHECK-DAG: @_ZN3FooIiE18static_data_memberE = linkonce_odr global + int& odr_use = Foo<int>::static_data_member; + + // A member class marked with the attribute is not part of the extern + // template declaration (it is not recursively instantiated), so its member + // functions must be emitted in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class122static_member_functionEv + Foo<int>::member_class1::static_member_function(); + + // A member function marked with the attribute in a member class is not + // part of the extern template declaration of the parent class template, so + // it must be emitted in this TU. + // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class222static_member_functionEv + Foo<int>::member_class2::static_member_function(); +} diff --git a/test/CodeGenCXX/attr-no-destroy-d54344.cpp b/test/CodeGenCXX/attr-no-destroy-d54344.cpp new file mode 100644 index 000000000000..2e004d6426d9 --- /dev/null +++ b/test/CodeGenCXX/attr-no-destroy-d54344.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK-ATTR +// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR -fno-c++-static-destructors %s -o - | FileCheck %s --check-prefix=CHECK-FLAG + +// Regression test for D54344. Class with no user-defined destructor +// that has an inherited member that has a non-trivial destructor +// and a non-default constructor will attempt to emit a destructor +// despite being marked as __attribute((no_destroy)) in which case +// it would trigger an assertion due to an incorrect assumption. + +// This test is more reliable with asserts to work as without +// the crash may (unlikely) could generate working but semantically +// incorrect code. + +class a { +public: + ~a(); +}; +class logger_base { + a d; +}; +class e : logger_base {}; +#ifndef NOATTR +__attribute((no_destroy)) +#endif +e g; + +// In the absence of the attribute and flag, both ctor and dtor should +// be emitted, check for that. +// CHECK: @__cxx_global_var_init +// CHECK: @__cxa_atexit + +// When attribute is enabled, the constructor should not be balanced +// by a destructor. Make sure we have the ctor but not the dtor +// registration. +// CHECK-ATTR: @__cxx_global_var_init +// CHECK-ATTR-NOT: @__cxa_atexit + +// Same scenario except with global flag (-fno-c++-static-destructors) +// supressing it instead of the attribute. +// CHECK-FLAG: @__cxx_global_var_init +// CHECK-FLAG-NOT: @__cxa_atexit diff --git a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp index 4dc2b67b4644..77e1ad771eca 100644 --- a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp +++ b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s -// Test ensures that this properly differentiates between types in different +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS +// Test ensures that this properly differentiates between types in different // namespaces. int __attribute__((target("sse4.2"))) foo(int) { return 0; } int __attribute__((target("arch=sandybridge"))) foo(int); @@ -17,38 +18,71 @@ int bar() { return foo(1) + ns::foo(2); } -// CHECK: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver -// CHECK: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver - -// CHECK: define i32 @_Z3fooi.sse4.2(i32) -// CHECK: ret i32 0 -// CHECK: define i32 @_Z3fooi.arch_ivybridge(i32) -// CHECK: ret i32 1 -// CHECK: define i32 @_Z3fooi(i32) -// CHECK: ret i32 2 - -// CHECK: define i32 @_ZN2ns3fooEi.sse4.2(i32) -// CHECK: ret i32 0 -// CHECK: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32) -// CHECK: ret i32 1 -// CHECK: define i32 @_ZN2ns3fooEi(i32) -// CHECK: ret i32 2 - -// CHECK: define i32 @_Z3barv() -// CHECK: call i32 @_Z3fooi.ifunc(i32 1) -// CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2) - -// CHECK: define i32 (i32)* @_Z3fooi.resolver() comdat -// CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge -// CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge -// CHECK: ret i32 (i32)* @_Z3fooi.sse4.2 -// CHECK: ret i32 (i32)* @_Z3fooi -// -// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat -// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge -// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge -// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2 -// CHECK: ret i32 (i32)* @_ZN2ns3fooEi - -// CHECK: declare i32 @_Z3fooi.arch_sandybridge(i32) -// CHECK: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32) +// LINUX: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver +// LINUX: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver + +// LINUX: define i32 @_Z3fooi.sse4.2(i32) +// LINUX: ret i32 0 +// LINUX: define i32 @_Z3fooi.arch_ivybridge(i32) +// LINUX: ret i32 1 +// LINUX: define i32 @_Z3fooi(i32) +// LINUX: ret i32 2 + +// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.sse4.2"(i32) +// WINDOWS: ret i32 0 +// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.arch_ivybridge"(i32) +// WINDOWS: ret i32 1 +// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z"(i32) +// WINDOWS: ret i32 2 + +// LINUX: define i32 @_ZN2ns3fooEi.sse4.2(i32) +// LINUX: ret i32 0 +// LINUX: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32) +// LINUX: ret i32 1 +// LINUX: define i32 @_ZN2ns3fooEi(i32) +// LINUX: ret i32 2 + +// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.sse4.2"(i32) +// WINDOWS: ret i32 0 +// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.arch_ivybridge"(i32) +// WINDOWS: ret i32 1 +// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z"(i32) +// WINDOWS: ret i32 2 + +// LINUX: define i32 @_Z3barv() +// LINUX: call i32 @_Z3fooi.ifunc(i32 1) +// LINUX: call i32 @_ZN2ns3fooEi.ifunc(i32 2) + +// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"() +// WINDOWS: call i32 @"?foo@@YAHH@Z.resolver"(i32 1) +// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.resolver"(i32 2) + +// LINUX: define i32 (i32)* @_Z3fooi.resolver() comdat +// LINUX: ret i32 (i32)* @_Z3fooi.arch_sandybridge +// LINUX: ret i32 (i32)* @_Z3fooi.arch_ivybridge +// LINUX: ret i32 (i32)* @_Z3fooi.sse4.2 +// LINUX: ret i32 (i32)* @_Z3fooi + +// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.resolver"(i32) comdat +// WINDOWS: call i32 @"?foo@@YAHH@Z.arch_sandybridge"(i32 %0) +// WINDOWS: call i32 @"?foo@@YAHH@Z.arch_ivybridge"(i32 %0) +// WINDOWS: call i32 @"?foo@@YAHH@Z.sse4.2"(i32 %0) +// WINDOWS: call i32 @"?foo@@YAHH@Z"(i32 %0) + +// LINUX: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat +// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge +// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge +// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2 +// LINUX: ret i32 (i32)* @_ZN2ns3fooEi + +// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.resolver"(i32) comdat +// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_sandybridge"(i32 %0) +// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_ivybridge"(i32 %0) +// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.sse4.2"(i32 %0) +// WINDOWS: call i32 @"?foo@ns@@YAHH@Z"(i32 %0) + +// LINUX: declare i32 @_Z3fooi.arch_sandybridge(i32) +// LINUX: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32) + +// WINDOWS: declare dso_local i32 @"?foo@@YAHH@Z.arch_sandybridge"(i32) +// WINDOWS: declare dso_local i32 @"?foo@ns@@YAHH@Z.arch_sandybridge"(i32) diff --git a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp index 290d6b5c6489..6336e190426b 100644 --- a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp +++ b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS void temp(); void temp(int); using FP = void(*)(int); @@ -31,15 +32,23 @@ int bar() { return Free(1) + (s.*Member)(2); } +// LINUX: @_Z3fooi.ifunc +// LINUX: @_ZN1S3fooEi.ifunc -// CHECK: @_Z3fooi.ifunc -// CHECK: @_ZN1S3fooEi.ifunc - -// CHECK: define i32 @_Z3barv() +// LINUX: define i32 @_Z3barv() // Store to Free of ifunc -// CHECK: store i32 (i32)* @_Z3fooi.ifunc +// LINUX: store i32 (i32)* @_Z3fooi.ifunc // Store to Member of ifunc -// CHECK: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]] +// LINUX: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]] // Call to 'f' with the ifunc -// CHECK: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc +// LINUX: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc + +// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"() +// Store to Free +// WINDOWS: store i32 (i32)* @"?foo@@YAHH@Z.resolver", i32 (i32)** +// Store to Member +// WINDOWS: store i8* bitcast (i32 (%struct.S*, i32)* @"?foo@S@@QEAAHH@Z.resolver" to i8*), i8** + +// Call to 'f' +// WINDOWS: call void @"?f@@YAXP6AHH@ZP8S@@EAAHH@Z@Z"(i32 (i32)* @"?foo@@YAHH@Z.resolver", i8* bitcast (i32 (%struct.S*, i32)* @"?foo@S@@QEAAHH@Z.resolver" to i8*)) diff --git a/test/CodeGenCXX/attr-target-mv-inalloca.cpp b/test/CodeGenCXX/attr-target-mv-inalloca.cpp new file mode 100644 index 000000000000..0b656220273f --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-inalloca.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS64 + +struct Foo { + Foo(); + Foo(const Foo &o); + ~Foo(); + int x; +}; +int __attribute__((target("default"))) bar(Foo o) { return o.x; } +int __attribute__((target("sse4.2"))) bar(Foo o) { return o.x + 1; } +int __attribute__((target("arch=ivybridge"))) bar(Foo o) { return o.x + 2; } + +void usage() { + Foo f; + bar(f); +} + +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca) +// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 +// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS: ret i32 %[[LOAD]] + +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca) +// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 +// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1 +// WINDOWS: ret i32 %[[ADD]] + +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca) +// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 +// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 2 +// WINDOWS: ret i32 %[[ADD]] + +// WINDOWS: define dso_local void @"?usage@@YAXXZ"() +// WINDOWS: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo +// WINDOWS: %[[ARGMEM:[0-9a-zA-Z]+]] = alloca inalloca <{ %struct.Foo }> +// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca %[[ARGMEM]]) + +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>*) +// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* %0) +// WINDOWS-NEXT: ret i32 %[[RET]] +// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* %0) +// WINDOWS-NEXT: ret i32 %[[RET]] +// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* %0) +// WINDOWS-NEXT: ret i32 %[[RET]] + + +// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(%struct.Foo* %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS64: ret i32 %[[LOAD]] + +// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(%struct.Foo* %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1 +// WINDOWS64: ret i32 %[[ADD]] + +// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(%struct.Foo* %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 +// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] +// WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 2 +// WINDOWS64: ret i32 %[[ADD]] + +// WINDOWS64: define dso_local void @"?usage@@YAXXZ"() +// WINDOWS64: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo +// WINDOWS64: %[[ARG:[0-9a-zA-Z.]+]] = alloca %struct.Foo +// WINDOWS64: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo* %[[ARG]]) + +// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo*) +// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(%struct.Foo* %0) +// WINDOWS64-NEXT: ret i32 %[[RET]] +// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(%struct.Foo* %0) +// WINDOWS64-NEXT: ret i32 %[[RET]] +// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z"(%struct.Foo* %0) +// WINDOWS64-NEXT: ret i32 %[[RET]] diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp index 2e5db3b705e4..a63737ed0330 100644 --- a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp +++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS struct S { int __attribute__((target("sse4.2"))) foo(int) { return 0; } @@ -64,74 +65,156 @@ int templ_use() { return a.foo(1) + b.foo(2); } -// CHECK: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver -// CHECK: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver -// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver -// CHECK: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver +// LINUX: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver +// LINUX: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver +// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver +// LINUX: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver // Templates: -// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver -// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver - -// CHECK: define i32 @_Z3barv() -// CHECK: %s = alloca %struct.S, align 1 -// CHECK: %s2 = alloca %struct.S, align 1 -// CHECK: %C = alloca %struct.ConvertTo, align 1 -// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 -// CHECK: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C) -// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 -// CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) - -// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat -// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge -// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_ - -// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat -// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge -// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv - -// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi - -// CHECK: define i32 @_Z4bar2v() -// CHECK:call i32 @_ZN2S23fooEi.ifunc -// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat -// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge -// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge -// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2 -// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi - -// CHECK: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32) -// CHECK: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32) -// CHECK: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32) - -// CHECK: define i32 @_Z9templ_usev() -// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc -// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc - - -// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat -// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge -// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge -// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 -// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi -// -// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat -// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge -// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge -// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2 -// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi - -// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) -// CHECK: ret i32 0 - -// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) - -// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) -// CHECK: ret i32 1 - -// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) -// CHECK: ret i32 2 - +// LINUX: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver +// LINUX: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver + +// LINUX: define i32 @_Z3barv() +// LINUX: %s = alloca %struct.S, align 1 +// LINUX: %s2 = alloca %struct.S, align 1 +// LINUX: %C = alloca %struct.ConvertTo, align 1 +// LINUX: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// LINUX: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C) +// LINUX: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// LINUX: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"() +// WINDOWS: %s = alloca %struct.S, align 1 +// WINDOWS: %s2 = alloca %struct.S, align 1 +// WINDOWS: %C = alloca %struct.ConvertTo, align 1 +// WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %s2 +// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* %C +// WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %s2 +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %s, i32 0) + +// LINUX: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat +// LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge +// LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_ + +// WINDOWS: define dso_local %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S*, %struct.S*) +// WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.arch_ivybridge" +// WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z" + +// LINUX: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat +// LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge +// LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv + +// WINDOWS: define dso_local void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo*, %struct.S*) +// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.arch_ivybridge" +// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ" + +// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S*, i32) +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2" +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z" + +// LINUX: define i32 @_Z4bar2v() +// LINUX: call i32 @_ZN2S23fooEi.ifunc + +// WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"() +// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.resolver" + +// LINUX: define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat +// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge +// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge +// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2 +// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi + +// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.resolver"(%struct.S2*, i32) +// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.sse4.2" +// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z" + +// LINUX: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32) +// LINUX: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32) +// LINUX: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32) + +// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.sse4.2"(%struct.S2* %this, i32) +// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"(%struct.S2* %this, i32) +// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z"(%struct.S2* %this, i32) + +// LINUX: define i32 @_Z9templ_usev() +// LINUX: call i32 @_ZN5templIiE3fooEi.ifunc +// LINUX: call i32 @_ZN5templIdE3fooEi.ifunc + +// WINDOWS: define dso_local i32 @"?templ_use@@YAHXZ"() +// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver" +// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver" + +// LINUX: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat +// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge +// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge +// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 +// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi + +// WINDOWS: define dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"(%struct.templ*, i32) +// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2" +// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z" + +// LINUX: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat +// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge +// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge +// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2 +// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi + +// WINDOWS: define dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"(%struct.templ.0*, i32) comdat +// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2" +// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z" + +// LINUX: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// LINUX: ret i32 0 + +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %this, i32) +// WINDOWS: ret i32 0 + +// LINUX: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) + +// WINDOWS: declare dso_local i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S*, i32) + +// LINUX: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// LINUX: ret i32 1 + +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %this, i32) +// WINDOWS: ret i32 1 + +// LINUX: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// LINUX: ret i32 2 + +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %this, i32) +// WINDOWS: ret i32 2 + +// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2 +// LINUX: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge +// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge +// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi + +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2" +// WINDOWS: declare dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z" + +// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2 +// LINUX: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge +// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge +// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi + +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2" +// WINDOWS: declare dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge" +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge" +// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z" diff --git a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp index 63353c12d29a..1c051b385384 100644 --- a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp +++ b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS struct S { int __attribute__((target("sse4.2"))) foo(int); int __attribute__((target("arch=sandybridge"))) foo(int); @@ -15,25 +16,46 @@ int bar() { return s.foo(0); } -// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver +// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver -// CHECK: define i32 @_ZN1S3fooEi(%struct.S* %this, i32) -// CHECK: ret i32 2 +// LINUX: define i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// LINUX: ret i32 2 -// CHECK: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) -// CHECK: ret i32 0 +// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %this, i32) +// WINDOWS: ret i32 2 -// CHECK: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) -// CHECK: ret i32 1 +// LINUX: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// LINUX: ret i32 0 -// CHECK: define i32 @_Z3barv() -// CHECK: %s = alloca %struct.S, align 1 -// CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) +// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %this, i32) +// WINDOWS: ret i32 0 -// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 -// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi +// LINUX: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// LINUX: ret i32 1 -// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) +// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %this, i32) +// WINDOWS: ret i32 1 + +// LINUX: define i32 @_Z3barv() +// LINUX: %s = alloca %struct.S, align 1 +// LINUX: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"() +// WINDOWS: %s = alloca %struct.S, align 1 +// WINDOWS: %call = call i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %s, i32 0) + +// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S*, i32) comdat +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S* %0, i32 %1) +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %0, i32 %1) +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %0, i32 %1) +// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %0, i32 %1) + +// LINUX: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) + +// WINDOWS: declare dso_local i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S*, i32) diff --git a/test/CodeGenCXX/attr-target-mv-overloads.cpp b/test/CodeGenCXX/attr-target-mv-overloads.cpp index c72ea77fa46f..a213d247cb1f 100644 --- a/test/CodeGenCXX/attr-target-mv-overloads.cpp +++ b/test/CodeGenCXX/attr-target-mv-overloads.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; } int __attribute__((target("arch=sandybridge"))) foo_overload(int); @@ -13,38 +14,69 @@ int bar2() { return foo_overload() + foo_overload(1); } -// CHECK: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver -// CHECK: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver - - -// CHECK: define i32 @_Z12foo_overloadi.sse4.2(i32) -// CHECK: ret i32 0 -// CHECK: define i32 @_Z12foo_overloadi.arch_ivybridge(i32) -// CHECK: ret i32 1 -// CHECK: define i32 @_Z12foo_overloadi(i32) -// CHECK: ret i32 2 -// CHECK: define i32 @_Z12foo_overloadv.sse4.2() -// CHECK: ret i32 0 -// CHECK: define i32 @_Z12foo_overloadv.arch_ivybridge() -// CHECK: ret i32 1 -// CHECK: define i32 @_Z12foo_overloadv() -// CHECK: ret i32 2 - -// CHECK: define i32 @_Z4bar2v() -// CHECK: call i32 @_Z12foo_overloadv.ifunc() -// CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1) - -// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() comdat -// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge -// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge -// CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2 -// CHECK: ret i32 ()* @_Z12foo_overloadv - -// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat -// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge -// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge -// CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2 -// CHECK: ret i32 (i32)* @_Z12foo_overloadi - -// CHECK: declare i32 @_Z12foo_overloadv.arch_sandybridge() -// CHECK: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32) +// LINUX: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver +// LINUX: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver + +// LINUX: define i32 @_Z12foo_overloadi.sse4.2(i32) +// LINUX: ret i32 0 +// LINUX: define i32 @_Z12foo_overloadi.arch_ivybridge(i32) +// LINUX: ret i32 1 +// LINUX: define i32 @_Z12foo_overloadi(i32) +// LINUX: ret i32 2 +// LINUX: define i32 @_Z12foo_overloadv.sse4.2() +// LINUX: ret i32 0 +// LINUX: define i32 @_Z12foo_overloadv.arch_ivybridge() +// LINUX: ret i32 1 +// LINUX: define i32 @_Z12foo_overloadv() +// LINUX: ret i32 2 + +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.sse4.2"(i32) +// WINDOWS: ret i32 0 +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.arch_ivybridge"(i32) +// WINDOWS: ret i32 1 +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z"(i32) +// WINDOWS: ret i32 2 +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.sse4.2"() +// WINDOWS: ret i32 0 +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.arch_ivybridge"() +// WINDOWS: ret i32 1 +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ"() +// WINDOWS: ret i32 2 + +// LINUX: define i32 @_Z4bar2v() +// LINUX: call i32 @_Z12foo_overloadv.ifunc() +// LINUX: call i32 @_Z12foo_overloadi.ifunc(i32 1) + +// WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"() +// WINDOWS: call i32 @"?foo_overload@@YAHXZ.resolver"() +// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.resolver"(i32 1) + +// LINUX: define i32 ()* @_Z12foo_overloadv.resolver() comdat +// LINUX: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge +// LINUX: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge +// LINUX: ret i32 ()* @_Z12foo_overloadv.sse4.2 +// LINUX: ret i32 ()* @_Z12foo_overloadv + +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.resolver"() comdat +// WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_sandybridge" +// WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_ivybridge" +// WINDOWS: call i32 @"?foo_overload@@YAHXZ.sse4.2" +// WINDOWS: call i32 @"?foo_overload@@YAHXZ" + +// LINUX: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat +// LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge +// LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge +// LINUX: ret i32 (i32)* @_Z12foo_overloadi.sse4.2 +// LINUX: ret i32 (i32)* @_Z12foo_overloadi + +// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.resolver"(i32) comdat +// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_sandybridge" +// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_ivybridge" +// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.sse4.2" +// WINDOWS: call i32 @"?foo_overload@@YAHH@Z" + +// LINUX: declare i32 @_Z12foo_overloadv.arch_sandybridge() +// LINUX: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32) + +// WINDOWS: declare dso_local i32 @"?foo_overload@@YAHXZ.arch_sandybridge"() +// WINDOWS: declare dso_local i32 @"?foo_overload@@YAHH@Z.arch_sandybridge"(i32) diff --git a/test/CodeGenCXX/auto-var-init.cpp b/test/CodeGenCXX/auto-var-init.cpp new file mode 100644 index 000000000000..0d13c0af4e8f --- /dev/null +++ b/test/CodeGenCXX/auto-var-init.cpp @@ -0,0 +1,1350 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO + +template<typename T> void used(T &) noexcept; + +#define TEST_UNINIT(NAME, TYPE) \ + using type_##NAME = TYPE; \ + void test_##NAME##_uninit() { \ + type_##NAME uninit; \ + used(uninit); \ + } + +// Value initialization on scalars, aggregate initialization on aggregates. +#define TEST_BRACES(NAME, TYPE) \ + using type_##NAME = TYPE; \ + void test_##NAME##_braces() { \ + type_##NAME braces = {}; \ + used(braces); \ + } + +#define TEST_CUSTOM(NAME, TYPE, ...) \ + using type_##NAME = TYPE; \ + void test_##NAME##_custom() { \ + type_##NAME custom __VA_ARGS__; \ + used(custom); \ + } + +// None of the synthesized globals should contain `undef`. +// PATTERN-NOT: undef +// ZERO-NOT: undef + +// PATTERN: @__const.test_empty_uninit.uninit = private unnamed_addr constant %struct.empty { i8 -86 }, align 1 +struct empty {}; +// PATTERN: @__const.test_small_uninit.uninit = private unnamed_addr constant %struct.small { i8 -86 }, align 1 +// PATTERN: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1 +// ZERO: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1 +struct small { char c; }; +// PATTERN: @__const.test_smallinit_uninit.uninit = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1 +// PATTERN: @__const.test_smallinit_braces.braces = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1 +// PATTERN: @__const.test_smallinit_custom.custom = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1 +struct smallinit { char c = 42; }; +// PATTERN: @__const.test_smallpartinit_uninit.uninit = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1 +// PATTERN: @__const.test_smallpartinit_braces.braces = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1 +// PATTERN: @__const.test_smallpartinit_custom.custom = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1 +struct smallpartinit { char c = 42, d; }; +// PATTERN: @__const.test_nullinit_uninit.uninit = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8 +// PATTERN: @__const.test_nullinit_braces.braces = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8 +// PATTERN: @__const.test_nullinit_custom.custom = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8 +struct nullinit { char* null = nullptr; }; +// PATTERN: @__const.test_padded_uninit.uninit = private unnamed_addr constant %struct.padded { i8 -86, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_padded_custom.custom = private unnamed_addr constant %struct.padded { i8 42, i32 13371337 }, align 4 +// ZERO: @__const.test_padded_custom.custom = private unnamed_addr constant %struct.padded { i8 42, i32 13371337 }, align 4 +struct padded { char c; int i; }; +// PATTERN: @__const.test_paddednullinit_uninit.uninit = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_paddednullinit_braces.braces = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_paddednullinit_custom.custom = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4 +struct paddednullinit { char c = 0; int i = 0; }; +// PATTERN: @__const.test_bitfield_uninit.uninit = private unnamed_addr constant %struct.bitfield { i8 -86, [3 x i8] c"\AA\AA\AA" }, align 4 +// PATTERN: @__const.test_bitfield_custom.custom = private unnamed_addr constant %struct.bitfield { i8 20, [3 x i8] zeroinitializer }, align 4 +// ZERO: @__const.test_bitfield_custom.custom = private unnamed_addr constant %struct.bitfield { i8 20, [3 x i8] zeroinitializer }, align 4 +struct bitfield { int i : 4; int j : 2; }; +// PATTERN: @__const.test_bitfieldaligned_uninit.uninit = private unnamed_addr constant %struct.bitfieldaligned { i8 -86, [3 x i8] c"\AA\AA\AA", i8 -86, [3 x i8] c"\AA\AA\AA" }, align 4 +// PATTERN: @__const.test_bitfieldaligned_custom.custom = private unnamed_addr constant %struct.bitfieldaligned { i8 4, [3 x i8] zeroinitializer, i8 1, [3 x i8] zeroinitializer }, align 4 +// ZERO: @__const.test_bitfieldaligned_custom.custom = private unnamed_addr constant %struct.bitfieldaligned { i8 4, [3 x i8] zeroinitializer, i8 1, [3 x i8] zeroinitializer }, align 4 +struct bitfieldaligned { int i : 4; int : 0; int j : 2; }; +struct big { unsigned a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; }; +// PATTERN: @__const.test_arraytail_uninit.uninit = private unnamed_addr constant %struct.arraytail { i32 -1431655766, [0 x i32] zeroinitializer }, align 4 +// PATTERN: @__const.test_arraytail_custom.custom = private unnamed_addr constant %struct.arraytail { i32 57005, [0 x i32] zeroinitializer }, align 4 +// ZERO: @__const.test_arraytail_custom.custom = private unnamed_addr constant %struct.arraytail { i32 57005, [0 x i32] zeroinitializer }, align 4 +struct arraytail { int i; int arr[]; }; +// PATTERN: @__const.test_int1_uninit.uninit = private unnamed_addr constant [1 x i32] [i32 -1431655766], align 4 +// PATTERN: @__const.test_int1_custom.custom = private unnamed_addr constant [1 x i32] [i32 858993459], align 4 +// ZERO: @__const.test_int1_custom.custom = private unnamed_addr constant [1 x i32] [i32 858993459], align 4 +// PATTERN: @__const.test_bool4_uninit.uninit = private unnamed_addr constant [4 x i8] c"\AA\AA\AA\AA", align 1 +// PATTERN: @__const.test_bool4_custom.custom = private unnamed_addr constant [4 x i8] c"\01\01\01\01", align 1 +// ZERO: @__const.test_bool4_custom.custom = private unnamed_addr constant [4 x i8] c"\01\01\01\01", align 1 +// PATTERN: @__const.test_intptr4_uninit.uninit = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*)], align 16 +// PATTERN: @__const.test_intptr4_custom.custom = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*)], align 16 +// ZERO: @__const.test_intptr4_custom.custom = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*)], align 16 +// PATTERN: @__const.test_tailpad4_uninit.uninit = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }], align 16 +// PATTERN: @__const.test_tailpad4_custom.custom = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }], align 16 +// ZERO: @__const.test_tailpad4_custom.custom = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }], align 16 +struct tailpad { short s; char c; }; +// PATTERN: @__const.test_atomicnotlockfree_uninit.uninit = private unnamed_addr constant %struct.notlockfree { [4 x i64] [i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206] }, align 8 +struct notlockfree { long long a[4]; }; +// PATTERN: @__const.test_atomicpadded_uninit.uninit = private unnamed_addr constant %struct.padded { i8 -86, i32 -1431655766 }, align 8 +// PATTERN: @__const.test_atomictailpad_uninit.uninit = private unnamed_addr constant %struct.tailpad { i16 -21846, i8 -86 }, align 4 +// PATTERN: @__const.test_complexfloat_uninit.uninit = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4 +// PATTERN: @__const.test_complexfloat_braces.braces = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4 +// PATTERN: @__const.test_complexfloat_custom.custom = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4 +// PATTERN: @__const.test_complexdouble_uninit.uninit = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8 +// PATTERN: @__const.test_complexdouble_braces.braces = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8 +// PATTERN: @__const.test_complexdouble_custom.custom = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8 +// PATTERN: @__const.test_semivolatile_uninit.uninit = private unnamed_addr constant %struct.semivolatile { i32 -1431655766, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_semivolatile_custom.custom = private unnamed_addr constant %struct.semivolatile { i32 1145324612, i32 1145324612 }, align 4 +struct semivolatile { int i; volatile int vi; }; +// PATTERN: @__const.test_semivolatileinit_uninit.uninit = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_semivolatileinit_braces.braces = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4 +// PATTERN: @__const.test_semivolatileinit_custom.custom = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4 +// ZERO: @__const.test_semivolatile_custom.custom = private unnamed_addr constant %struct.semivolatile { i32 1145324612, i32 1145324612 }, align 4 +struct semivolatileinit { int i = 0x11111111; volatile int vi = 0x11111111; }; +// PATTERN: @__const.test_base_uninit.uninit = private unnamed_addr constant %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, align 8 +// PATTERN: @__const.test_base_braces.braces = private unnamed_addr constant %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, align 8 +struct base { virtual ~base(); }; +// PATTERN: @__const.test_derived_uninit.uninit = private unnamed_addr constant %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } }, align 8 +// PATTERN: @__const.test_derived_braces.braces = private unnamed_addr constant %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } }, align 8 +struct derived : public base {}; +// PATTERN: @__const.test_virtualderived_uninit.uninit = private unnamed_addr constant %struct.virtualderived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } } }, align 8 +// PATTERN: @__const.test_virtualderived_braces.braces = private unnamed_addr constant %struct.virtualderived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } } }, align 8 +struct virtualderived : public virtual base, public virtual derived {}; +// PATTERN: @__const.test_matching_uninit.uninit = private unnamed_addr constant %union.matching { i32 -1431655766 }, align 4 +// PATTERN: @__const.test_matching_custom.custom = private unnamed_addr constant { float } { float 6.145500e+04 }, align 4 +union matching { int i; float f; }; +// PATTERN: @__const.test_matchingreverse_uninit.uninit = private unnamed_addr constant %union.matchingreverse { float 0xFFFFFFFFE0000000 }, align 4 +// PATTERN: @__const.test_matchingreverse_custom.custom = private unnamed_addr constant { i32 } { i32 61455 }, align 4 +// ZERO: @__const.test_matching_custom.custom = private unnamed_addr constant { float } { float 6.145500e+04 }, align 4 +union matchingreverse { float f; int i; }; +// PATTERN: @__const.test_unmatched_uninit.uninit = private unnamed_addr constant %union.unmatched { i32 -1431655766 }, align 4 +// PATTERN: @__const.test_unmatched_custom.custom = private unnamed_addr constant %union.unmatched { i32 1001242351 }, align 4 +// ZERO: @__const.test_matchingreverse_custom.custom = private unnamed_addr constant { i32 } { i32 61455 }, align 4 +union unmatched { char c; int i; }; +// PATTERN: @__const.test_unmatchedreverse_uninit.uninit = private unnamed_addr constant %union.unmatchedreverse { i32 -1431655766 }, align 4 +// PATTERN: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4 +// ZERO: @__const.test_unmatched_custom.custom = private unnamed_addr constant %union.unmatched { i32 1001242351 }, align 4 +union unmatchedreverse { int i; char c; }; +// PATTERN: @__const.test_unmatchedfp_uninit.uninit = private unnamed_addr constant %union.unmatchedfp { double 0xFFFFFFFFFFFFFFFF }, align 8 +// PATTERN: @__const.test_unmatchedfp_custom.custom = private unnamed_addr constant %union.unmatchedfp { double 0x400921FB54442D18 }, align 8 +// ZERO: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4 +// ZERO: @__const.test_unmatchedfp_custom.custom = private unnamed_addr constant %union.unmatchedfp { double 0x400921FB54442D18 }, align 8 +union unmatchedfp { float f; double d; }; +enum emptyenum {}; +enum smallenum { VALUE }; + +extern "C" { + +TEST_UNINIT(char, char); +// CHECK-LABEL: @test_char_uninit() +// CHECK: %uninit = alloca i8, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_char_uninit() +// PATTERN: store i8 -86, i8* %uninit, align 1 +// ZERO-LABEL: @test_char_uninit() +// ZERO: store i8 0, i8* %uninit, align 1 + +TEST_BRACES(char, char); +// CHECK-LABEL: @test_char_braces() +// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(uchar, unsigned char); +// CHECK-LABEL: @test_uchar_uninit() +// CHECK: %uninit = alloca i8, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_uchar_uninit() +// PATTERN: store i8 -86, i8* %uninit, align 1 +// ZERO-LABEL: @test_uchar_uninit() +// ZERO: store i8 0, i8* %uninit, align 1 + +TEST_BRACES(uchar, unsigned char); +// CHECK-LABEL: @test_uchar_braces() +// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(schar, signed char); +// CHECK-LABEL: @test_schar_uninit() +// CHECK: %uninit = alloca i8, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_schar_uninit() +// PATTERN: store i8 -86, i8* %uninit, align 1 +// ZERO-LABEL: @test_schar_uninit() +// ZERO: store i8 0, i8* %uninit, align 1 + +TEST_BRACES(schar, signed char); +// CHECK-LABEL: @test_schar_braces() +// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(wchar_t, wchar_t); +// CHECK-LABEL: @test_wchar_t_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_wchar_t_uninit() +// PATTERN: store i32 -1431655766, i32* %uninit, align +// ZERO-LABEL: @test_wchar_t_uninit() +// ZERO: store i32 0, i32* %uninit, align + +TEST_BRACES(wchar_t, wchar_t); +// CHECK-LABEL: @test_wchar_t_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(short, short); +// CHECK-LABEL: @test_short_uninit() +// CHECK: %uninit = alloca i16, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_short_uninit() +// PATTERN: store i16 -21846, i16* %uninit, align +// ZERO-LABEL: @test_short_uninit() +// ZERO: store i16 0, i16* %uninit, align + +TEST_BRACES(short, short); +// CHECK-LABEL: @test_short_braces() +// CHECK: %braces = alloca i16, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i16 0, i16* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(ushort, unsigned short); +// CHECK-LABEL: @test_ushort_uninit() +// CHECK: %uninit = alloca i16, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_ushort_uninit() +// PATTERN: store i16 -21846, i16* %uninit, align +// ZERO-LABEL: @test_ushort_uninit() +// ZERO: store i16 0, i16* %uninit, align + +TEST_BRACES(ushort, unsigned short); +// CHECK-LABEL: @test_ushort_braces() +// CHECK: %braces = alloca i16, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i16 0, i16* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(int, int); +// CHECK-LABEL: @test_int_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_int_uninit() +// PATTERN: store i32 -1431655766, i32* %uninit, align +// ZERO-LABEL: @test_int_uninit() +// ZERO: store i32 0, i32* %uninit, align + +TEST_BRACES(int, int); +// CHECK-LABEL: @test_int_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(unsigned, unsigned); +// CHECK-LABEL: @test_unsigned_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_unsigned_uninit() +// PATTERN: store i32 -1431655766, i32* %uninit, align +// ZERO-LABEL: @test_unsigned_uninit() +// ZERO: store i32 0, i32* %uninit, align + +TEST_BRACES(unsigned, unsigned); +// CHECK-LABEL: @test_unsigned_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(long, long); +// CHECK-LABEL: @test_long_uninit() +// CHECK: %uninit = alloca i64, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_long_uninit() +// PATTERN: store i64 -6148914691236517206, i64* %uninit, align +// ZERO-LABEL: @test_long_uninit() +// ZERO: store i64 0, i64* %uninit, align + +TEST_BRACES(long, long); +// CHECK-LABEL: @test_long_braces() +// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(ulong, unsigned long); +// CHECK-LABEL: @test_ulong_uninit() +// CHECK: %uninit = alloca i64, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_ulong_uninit() +// PATTERN: store i64 -6148914691236517206, i64* %uninit, align +// ZERO-LABEL: @test_ulong_uninit() +// ZERO: store i64 0, i64* %uninit, align + +TEST_BRACES(ulong, unsigned long); +// CHECK-LABEL: @test_ulong_braces() +// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(longlong, long long); +// CHECK-LABEL: @test_longlong_uninit() +// CHECK: %uninit = alloca i64, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_longlong_uninit() +// PATTERN: store i64 -6148914691236517206, i64* %uninit, align +// ZERO-LABEL: @test_longlong_uninit() +// ZERO: store i64 0, i64* %uninit, align + +TEST_BRACES(longlong, long long); +// CHECK-LABEL: @test_longlong_braces() +// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(ulonglong, unsigned long long); +// CHECK-LABEL: @test_ulonglong_uninit() +// CHECK: %uninit = alloca i64, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_ulonglong_uninit() +// PATTERN: store i64 -6148914691236517206, i64* %uninit, align +// ZERO-LABEL: @test_ulonglong_uninit() +// ZERO: store i64 0, i64* %uninit, align + +TEST_BRACES(ulonglong, unsigned long long); +// CHECK-LABEL: @test_ulonglong_braces() +// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(int128, __int128); +// CHECK-LABEL: @test_int128_uninit() +// CHECK: %uninit = alloca i128, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_int128_uninit() +// PATTERN: store i128 -113427455640312821154458202477256070486, i128* %uninit, align +// ZERO-LABEL: @test_int128_uninit() +// ZERO: store i128 0, i128* %uninit, align + +TEST_BRACES(int128, __int128); +// CHECK-LABEL: @test_int128_braces() +// CHECK: %braces = alloca i128, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i128 0, i128* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(uint128, unsigned __int128); +// CHECK-LABEL: @test_uint128_uninit() +// CHECK: %uninit = alloca i128, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_uint128_uninit() +// PATTERN: store i128 -113427455640312821154458202477256070486, i128* %uninit, align +// ZERO-LABEL: @test_uint128_uninit() +// ZERO: store i128 0, i128* %uninit, align + +TEST_BRACES(uint128, unsigned __int128); +// CHECK-LABEL: @test_uint128_braces() +// CHECK: %braces = alloca i128, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i128 0, i128* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + + +TEST_UNINIT(fp16, __fp16); +// CHECK-LABEL: @test_fp16_uninit() +// CHECK: %uninit = alloca half, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_fp16_uninit() +// PATTERN: store half 0xHFFFF, half* %uninit, align +// ZERO-LABEL: @test_fp16_uninit() +// ZERO: store half 0xH0000, half* %uninit, align + +TEST_BRACES(fp16, __fp16); +// CHECK-LABEL: @test_fp16_braces() +// CHECK: %braces = alloca half, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store half 0xH0000, half* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(float, float); +// CHECK-LABEL: @test_float_uninit() +// CHECK: %uninit = alloca float, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_float_uninit() +// PATTERN: store float 0xFFFFFFFFE0000000, float* %uninit, align +// ZERO-LABEL: @test_float_uninit() +// ZERO: store float 0.000000e+00, float* %uninit, align + +TEST_BRACES(float, float); +// CHECK-LABEL: @test_float_braces() +// CHECK: %braces = alloca float, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store float 0.000000e+00, float* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(double, double); +// CHECK-LABEL: @test_double_uninit() +// CHECK: %uninit = alloca double, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_double_uninit() +// PATTERN: store double 0xFFFFFFFFFFFFFFFF, double* %uninit, align +// ZERO-LABEL: @test_double_uninit() +// ZERO: store double 0.000000e+00, double* %uninit, align + +TEST_BRACES(double, double); +// CHECK-LABEL: @test_double_braces() +// CHECK: %braces = alloca double, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store double 0.000000e+00, double* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(longdouble, long double); +// CHECK-LABEL: @test_longdouble_uninit() +// CHECK: %uninit = alloca x86_fp80, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_longdouble_uninit() +// PATTERN: store x86_fp80 0xKFFFFFFFFFFFFFFFFFFFF, x86_fp80* %uninit, align +// ZERO-LABEL: @test_longdouble_uninit() +// ZERO: store x86_fp80 0xK00000000000000000000, x86_fp80* %uninit, align + +TEST_BRACES(longdouble, long double); +// CHECK-LABEL: @test_longdouble_braces() +// CHECK: %braces = alloca x86_fp80, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store x86_fp80 0xK00000000000000000000, x86_fp80* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + + +TEST_UNINIT(intptr, int*); +// CHECK-LABEL: @test_intptr_uninit() +// CHECK: %uninit = alloca i32*, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_intptr_uninit() +// PATTERN: store i32* inttoptr (i64 -6148914691236517206 to i32*), i32** %uninit, align +// ZERO-LABEL: @test_intptr_uninit() +// ZERO: store i32* null, i32** %uninit, align + +TEST_BRACES(intptr, int*); +// CHECK-LABEL: @test_intptr_braces() +// CHECK: %braces = alloca i32*, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32* null, i32** %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(intptrptr, int**); +// CHECK-LABEL: @test_intptrptr_uninit() +// CHECK: %uninit = alloca i32**, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_intptrptr_uninit() +// PATTERN: store i32** inttoptr (i64 -6148914691236517206 to i32**), i32*** %uninit, align +// ZERO-LABEL: @test_intptrptr_uninit() +// ZERO: store i32** null, i32*** %uninit, align + +TEST_BRACES(intptrptr, int**); +// CHECK-LABEL: @test_intptrptr_braces() +// CHECK: %braces = alloca i32**, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32** null, i32*** %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(function, void(*)()); +// CHECK-LABEL: @test_function_uninit() +// CHECK: %uninit = alloca void ()*, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_function_uninit() +// PATTERN: store void ()* inttoptr (i64 -6148914691236517206 to void ()*), void ()** %uninit, align +// ZERO-LABEL: @test_function_uninit() +// ZERO: store void ()* null, void ()** %uninit, align + +TEST_BRACES(function, void(*)()); +// CHECK-LABEL: @test_function_braces() +// CHECK: %braces = alloca void ()*, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store void ()* null, void ()** %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(bool, bool); +// CHECK-LABEL: @test_bool_uninit() +// CHECK: %uninit = alloca i8, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_bool_uninit() +// PATTERN: store i8 -86, i8* %uninit, align 1 +// ZERO-LABEL: @test_bool_uninit() +// ZERO: store i8 0, i8* %uninit, align 1 + +TEST_BRACES(bool, bool); +// CHECK-LABEL: @test_bool_braces() +// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + + +TEST_UNINIT(empty, empty); +// CHECK-LABEL: @test_empty_uninit() +// CHECK: %uninit = alloca %struct.empty, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_empty_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_empty_uninit.uninit +// ZERO-LABEL: @test_empty_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(empty, empty); +// CHECK-LABEL: @test_empty_braces() +// CHECK: %braces = alloca %struct.empty, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(small, small); +// CHECK-LABEL: @test_small_uninit() +// CHECK: %uninit = alloca %struct.small, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_small_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_small_uninit.uninit +// ZERO-LABEL: @test_small_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(small, small); +// CHECK-LABEL: @test_small_braces() +// CHECK: %braces = alloca %struct.small, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 1, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(small, small, { 42 }); +// CHECK-LABEL: @test_small_custom() +// CHECK: %custom = alloca %struct.small, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(smallinit, smallinit); +// CHECK-LABEL: @test_smallinit_uninit() +// CHECK: %uninit = alloca %struct.smallinit, align +// CHECK-NEXT: call void @{{.*}}smallinit{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) + +TEST_BRACES(smallinit, smallinit); +// CHECK-LABEL: @test_smallinit_braces() +// CHECK: %braces = alloca %struct.smallinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallinit, %struct.smallinit* %braces, i32 0, i32 0 +// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(smallinit, smallinit, { 100 }); +// CHECK-LABEL: @test_smallinit_custom() +// CHECK: %custom = alloca %struct.smallinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallinit, %struct.smallinit* %custom, i32 0, i32 0 +// CHECK-NEXT: store i8 100, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(smallpartinit, smallpartinit); +// CHECK-LABEL: @test_smallpartinit_uninit() +// CHECK: %uninit = alloca %struct.smallpartinit, align +// CHECK-NEXT: call void @{{.*}}smallpartinit{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_smallpartinit_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_smallpartinit_uninit.uninit +// ZERO-LABEL: @test_smallpartinit_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(smallpartinit, smallpartinit); +// CHECK-LABEL: @test_smallpartinit_braces() +// CHECK: %braces = alloca %struct.smallpartinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %braces, i32 0, i32 0 +// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: %[[D:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %braces, i32 0, i32 1 +// CHECK-NEXT: store i8 0, i8* %[[D]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(smallpartinit, smallpartinit, { 100, 42 }); +// CHECK-LABEL: @test_smallpartinit_custom() +// CHECK: %custom = alloca %struct.smallpartinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %custom, i32 0, i32 0 +// CHECK-NEXT: store i8 100, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: %[[D:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %custom, i32 0, i32 1 +// CHECK-NEXT: store i8 42, i8* %[[D]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(nullinit, nullinit); +// CHECK-LABEL: @test_nullinit_uninit() +// CHECK: %uninit = alloca %struct.nullinit, align +// CHECK-NEXT: call void @{{.*}}nullinit{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) + +TEST_BRACES(nullinit, nullinit); +// CHECK-LABEL: @test_nullinit_braces() +// CHECK: %braces = alloca %struct.nullinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[N:[^ ]*]] = getelementptr inbounds %struct.nullinit, %struct.nullinit* %braces, i32 0, i32 0 +// CHECK-NEXT: store i8* null, i8** %[[N]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(nullinit, nullinit, { (char*)"derp" }); +// CHECK-LABEL: @test_nullinit_custom() +// CHECK: %custom = alloca %struct.nullinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[N:[^ ]*]] = getelementptr inbounds %struct.nullinit, %struct.nullinit* %custom, i32 0, i32 0 +// CHECK-NEXT: store i8* getelementptr inbounds {{.*}}, i8** %[[N]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(padded, padded); +// CHECK-LABEL: @test_padded_uninit() +// CHECK: %uninit = alloca %struct.padded, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_padded_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_padded_uninit.uninit +// ZERO-LABEL: @test_padded_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(padded, padded); +// CHECK-LABEL: @test_padded_braces() +// CHECK: %braces = alloca %struct.padded, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(padded, padded, { 42, 13371337 }); +// CHECK-LABEL: @test_padded_custom() +// CHECK: %custom = alloca %struct.padded, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(paddednullinit, paddednullinit); +// CHECK-LABEL: @test_paddednullinit_uninit() +// CHECK: %uninit = alloca %struct.paddednullinit, align +// CHECK-NEXT: call void @{{.*}}paddednullinit{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_paddednullinit_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_paddednullinit_uninit.uninit +// ZERO-LABEL: @test_paddednullinit_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(paddednullinit, paddednullinit); +// CHECK-LABEL: @test_paddednullinit_braces() +// CHECK: %braces = alloca %struct.paddednullinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %braces, i32 0, i32 0 +// CHECK-NEXT: store i8 0, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %braces, i32 0, i32 1 +// CHECK-NEXT: store i32 0, i32* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(paddednullinit, paddednullinit, { 42, 13371337 }); +// CHECK-LABEL: @test_paddednullinit_custom() +// CHECK: %custom = alloca %struct.paddednullinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %custom, i32 0, i32 0 +// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]] +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %custom, i32 0, i32 1 +// CHECK-NEXT: store i32 13371337, i32* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(bitfield, bitfield); +// CHECK-LABEL: @test_bitfield_uninit() +// CHECK: %uninit = alloca %struct.bitfield, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_bitfield_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bitfield_uninit.uninit +// ZERO-LABEL: @test_bitfield_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(bitfield, bitfield); +// CHECK-LABEL: @test_bitfield_braces() +// CHECK: %braces = alloca %struct.bitfield, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(bitfield, bitfield, { 4, 1 }); +// CHECK-LABEL: @test_bitfield_custom() +// CHECK: %custom = alloca %struct.bitfield, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(bitfieldaligned, bitfieldaligned); +// CHECK-LABEL: @test_bitfieldaligned_uninit() +// CHECK: %uninit = alloca %struct.bitfieldaligned, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_bitfieldaligned_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bitfieldaligned_uninit.uninit +// ZERO-LABEL: @test_bitfieldaligned_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(bitfieldaligned, bitfieldaligned); +// CHECK-LABEL: @test_bitfieldaligned_braces() +// CHECK: %braces = alloca %struct.bitfieldaligned, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(bitfieldaligned, bitfieldaligned, { 4, 1 }); +// CHECK-LABEL: @test_bitfieldaligned_custom() +// CHECK: %custom = alloca %struct.bitfieldaligned, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(big, big); +// CHECK-LABEL: @test_big_uninit() +// CHECK: %uninit = alloca %struct.big, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_big_uninit() +// PATTERN: call void @llvm.memset{{.*}}, i8 -86, +// ZERO-LABEL: @test_big_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(big, big); +// CHECK-LABEL: @test_big_braces() +// CHECK: %braces = alloca %struct.big, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 104, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(big, big, { 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA }); +// CHECK-LABEL: @test_big_custom() +// CHECK: %custom = alloca %struct.big, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 -86, i64 104, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(arraytail, arraytail); +// CHECK-LABEL: @test_arraytail_uninit() +// CHECK: %uninit = alloca %struct.arraytail, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_arraytail_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_arraytail_uninit.uninit +// ZERO-LABEL: @test_arraytail_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(arraytail, arraytail); +// CHECK-LABEL: @test_arraytail_braces() +// CHECK: %braces = alloca %struct.arraytail, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(arraytail, arraytail, { 0xdead }); +// CHECK-LABEL: @test_arraytail_custom() +// CHECK: %custom = alloca %struct.arraytail, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(int0, int[0]); +// CHECK-LABEL: @test_int0_uninit() +// CHECK: %uninit = alloca [0 x i32], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_int0_uninit() +// PATTERN: %uninit = alloca [0 x i32], align +// PATTERN-NEXT: call void @{{.*}}used{{.*}}%uninit) +// ZERO-LABEL: @test_int0_uninit() +// ZERO: %uninit = alloca [0 x i32], align +// ZERO-NEXT: call void @{{.*}}used{{.*}}%uninit) + +TEST_BRACES(int0, int[0]); +// CHECK-LABEL: @test_int0_braces() +// CHECK: %braces = alloca [0 x i32], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 0, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(int1, int[1]); +// CHECK-LABEL: @test_int1_uninit() +// CHECK: %uninit = alloca [1 x i32], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_int1_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_int1_uninit.uninit +// ZERO-LABEL: @test_int1_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(int1, int[1]); +// CHECK-LABEL: @test_int1_braces() +// CHECK: %braces = alloca [1 x i32], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(int1, int[1], { 0x33333333 }); +// CHECK-LABEL: @test_int1_custom() +// CHECK: %custom = alloca [1 x i32], align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(int64, int[64]); +// CHECK-LABEL: @test_int64_uninit() +// CHECK: %uninit = alloca [64 x i32], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_int64_uninit() +// PATTERN: call void @llvm.memset{{.*}}, i8 -86, +// ZERO-LABEL: @test_int64_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(int64, int[64]); +// CHECK-LABEL: @test_int64_braces() +// CHECK: %braces = alloca [64 x i32], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 256, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(int64, int[64], = { 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111 }); +// CHECK-LABEL: @test_int64_custom() +// CHECK: %custom = alloca [64 x i32], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 17, i64 256, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(bool4, bool[4]); +// CHECK-LABEL: @test_bool4_uninit() +// CHECK: %uninit = alloca [4 x i8], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_bool4_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bool4_uninit.uninit +// ZERO-LABEL: @test_bool4_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(bool4, bool[4]); +// CHECK-LABEL: @test_bool4_braces() +// CHECK: %braces = alloca [4 x i8], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(bool4, bool[4], { true, true, true, true }); +// CHECK-LABEL: @test_bool4_custom() +// CHECK: %custom = alloca [4 x i8], align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(intptr4, int*[4]); +// CHECK-LABEL: @test_intptr4_uninit() +// CHECK: %uninit = alloca [4 x i32*], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_intptr4_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_intptr4_uninit.uninit +// ZERO-LABEL: @test_intptr4_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(intptr4, int*[4]); +// CHECK-LABEL: @test_intptr4_braces() +// CHECK: %braces = alloca [4 x i32*], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 32, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + + TEST_CUSTOM(intptr4, int*[4], = { (int*)0x22222222, (int*)0x22222222, (int*)0x22222222, (int*)0x22222222 }); +// CHECK-LABEL: @test_intptr4_custom() +// CHECK: %custom = alloca [4 x i32*], align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(tailpad4, tailpad[4]); +// CHECK-LABEL: @test_tailpad4_uninit() +// CHECK: %uninit = alloca [4 x %struct.tailpad], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_tailpad4_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_tailpad4_uninit.uninit +// ZERO-LABEL: @test_tailpad4_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(tailpad4, tailpad[4]); +// CHECK-LABEL: @test_tailpad4_braces() +// CHECK: %braces = alloca [4 x %struct.tailpad], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 16, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(tailpad4, tailpad[4], { {257, 1}, {257, 1}, {257, 1}, {257, 1} }); +// CHECK-LABEL: @test_tailpad4_custom() +// CHECK: %custom = alloca [4 x %struct.tailpad], align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(tailpad9, tailpad[9]); +// CHECK-LABEL: @test_tailpad9_uninit() +// CHECK: %uninit = alloca [9 x %struct.tailpad], align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_tailpad9_uninit() +// PATTERN: call void @llvm.memset{{.*}}, i8 -86, +// ZERO-LABEL: @test_tailpad9_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(tailpad9, tailpad[9]); +// CHECK-LABEL: @test_tailpad9_braces() +// CHECK: %braces = alloca [9 x %struct.tailpad], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 36, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(tailpad9, tailpad[9], { {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1} }); +// CHECK-LABEL: @test_tailpad9_custom() +// CHECK: %custom = alloca [9 x %struct.tailpad], align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 1, i64 36, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(atomicbool, _Atomic(bool)); +// CHECK-LABEL: @test_atomicbool_uninit() +// CHECK: %uninit = alloca i8, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomicbool_uninit() +// PATTERN: store i8 -86, i8* %uninit, align 1 +// ZERO-LABEL: @test_atomicbool_uninit() +// ZERO: store i8 0, i8* %uninit, align 1 + +TEST_UNINIT(atomicint, _Atomic(int)); +// CHECK-LABEL: @test_atomicint_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomicint_uninit() +// PATTERN: store i32 -1431655766, i32* %uninit, align 4 +// ZERO-LABEL: @test_atomicint_uninit() +// ZERO: store i32 0, i32* %uninit, align 4 + +TEST_UNINIT(atomicdouble, _Atomic(double)); +// CHECK-LABEL: @test_atomicdouble_uninit() +// CHECK: %uninit = alloca double, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomicdouble_uninit() +// PATTERN: store double 0xFFFFFFFFFFFFFFFF, double* %uninit, align 8 +// ZERO-LABEL: @test_atomicdouble_uninit() +// ZERO: store double 0.000000e+00, double* %uninit, align 8 + +TEST_UNINIT(atomicnotlockfree, _Atomic(notlockfree)); +// CHECK-LABEL: @test_atomicnotlockfree_uninit() +// CHECK: %uninit = alloca %struct.notlockfree, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomicnotlockfree_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomicnotlockfree_uninit.uninit +// ZERO-LABEL: @test_atomicnotlockfree_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_UNINIT(atomicpadded, _Atomic(padded)); +// CHECK-LABEL: @test_atomicpadded_uninit() +// CHECK: %uninit = alloca %struct.padded, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomicpadded_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomicpadded_uninit.uninit +// ZERO-LABEL: @test_atomicpadded_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_UNINIT(atomictailpad, _Atomic(tailpad)); +// CHECK-LABEL: @test_atomictailpad_uninit() +// CHECK: %uninit = alloca %struct.tailpad, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_atomictailpad_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomictailpad_uninit.uninit +// ZERO-LABEL: @test_atomictailpad_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + + +TEST_UNINIT(complexfloat, _Complex float); +// CHECK-LABEL: @test_complexfloat_uninit() +// CHECK: %uninit = alloca { float, float }, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_complexfloat_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_complexfloat_uninit.uninit +// ZERO-LABEL: @test_complexfloat_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(complexfloat, _Complex float); +// CHECK-LABEL: @test_complexfloat_braces() +// CHECK: %braces = alloca { float, float }, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %braces, i32 0, i32 0 +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %braces, i32 0, i32 1 +// CHECK-NEXT: store float 0.000000e+00, float* %[[R]], align [[ALIGN]] +// CHECK-NEXT: store float 0.000000e+00, float* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(complexfloat, _Complex float, { 3.1415926535897932384626433, 3.1415926535897932384626433 }); +// CHECK-LABEL: @test_complexfloat_custom() +// CHECK: %custom = alloca { float, float }, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %custom, i32 0, i32 0 +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %custom, i32 0, i32 1 +// CHECK-NEXT: store float 0x400921FB60000000, float* %[[R]], align [[ALIGN]] +// CHECK-NEXT: store float 0x400921FB60000000, float* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(complexdouble, _Complex double); +// CHECK-LABEL: @test_complexdouble_uninit() +// CHECK: %uninit = alloca { double, double }, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_complexdouble_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_complexdouble_uninit.uninit +// ZERO-LABEL: @test_complexdouble_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(complexdouble, _Complex double); +// CHECK-LABEL: @test_complexdouble_braces() +// CHECK: %braces = alloca { double, double }, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %braces, i32 0, i32 0 +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %braces, i32 0, i32 1 +// CHECK-NEXT: store double 0.000000e+00, double* %[[R]], align [[ALIGN]] +// CHECK-NEXT: store double 0.000000e+00, double* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(complexdouble, _Complex double, { 3.1415926535897932384626433, 3.1415926535897932384626433 }); +// CHECK-LABEL: @test_complexdouble_custom() +// CHECK: %custom = alloca { double, double }, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %custom, i32 0, i32 0 +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %custom, i32 0, i32 1 +// CHECK-NEXT: store double 0x400921FB54442D18, double* %[[R]], align [[ALIGN]] +// CHECK-NEXT: store double 0x400921FB54442D18, double* %[[I]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(volatileint, volatile int); +// CHECK-LABEL: @test_volatileint_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_volatileint_uninit() +// PATTERN: store volatile i32 -1431655766, i32* %uninit, align 4 +// ZERO-LABEL: @test_volatileint_uninit() +// ZERO: store volatile i32 0, i32* %uninit, align 4 + +TEST_BRACES(volatileint, volatile int); +// CHECK-LABEL: @test_volatileint_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store volatile i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(semivolatile, semivolatile); +// CHECK-LABEL: @test_semivolatile_uninit() +// CHECK: %uninit = alloca %struct.semivolatile, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_semivolatile_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_semivolatile_uninit.uninit +// ZERO-LABEL: @test_semivolatile_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(semivolatile, semivolatile); +// CHECK-LABEL: @test_semivolatile_braces() +// CHECK: %braces = alloca %struct.semivolatile, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(semivolatile, semivolatile, { 0x44444444, 0x44444444 }); +// CHECK-LABEL: @test_semivolatile_custom() +// CHECK: %custom = alloca %struct.semivolatile, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(semivolatileinit, semivolatileinit); +// CHECK-LABEL: @test_semivolatileinit_uninit() +// CHECK: %uninit = alloca %struct.semivolatileinit, align +// CHECK-NEXT: call void @{{.*}}semivolatileinit{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) + +TEST_BRACES(semivolatileinit, semivolatileinit); +// CHECK-LABEL: @test_semivolatileinit_braces() +// CHECK: %braces = alloca %struct.semivolatileinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %braces, i32 0, i32 0 +// CHECK-NEXT: store i32 286331153, i32* %[[I]], align [[ALIGN]] +// CHECK-NEXT: %[[VI:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %braces, i32 0, i32 1 +// CHECK-NEXT: store volatile i32 286331153, i32* %[[VI]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(semivolatileinit, semivolatileinit, { 0x44444444, 0x44444444 }); +// CHECK-LABEL: @test_semivolatileinit_custom() +// CHECK: %custom = alloca %struct.semivolatileinit, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %custom, i32 0, i32 0 +// CHECK-NEXT: store i32 1145324612, i32* %[[I]], align [[ALIGN]] +// CHECK-NEXT: %[[VI:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %custom, i32 0, i32 1 +// CHECK-NEXT: store volatile i32 1145324612, i32* %[[VI]], align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(base, base); +// CHECK-LABEL: @test_base_uninit() +// CHECK: %uninit = alloca %struct.base, align +// CHECK-NEXT: call void @{{.*}}base{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_base_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit +// ZERO-LABEL: @test_base_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(base, base); +// CHECK-LABEL: @test_base_braces() +// CHECK: %braces = alloca %struct.base, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false) +// CHECK-NEXT: call void @{{.*}}base{{.*}}%braces) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(derived, derived); +// CHECK-LABEL: @test_derived_uninit() +// CHECK: %uninit = alloca %struct.derived, align +// CHECK-NEXT: call void @{{.*}}derived{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_derived_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_derived_uninit.uninit +// ZERO-LABEL: @test_derived_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(derived, derived); +// CHECK-LABEL: @test_derived_braces() +// CHECK: %braces = alloca %struct.derived, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false) +// CHECK-NEXT: call void @{{.*}}derived{{.*}}%braces) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_UNINIT(virtualderived, virtualderived); +// CHECK-LABEL: @test_virtualderived_uninit() +// CHECK: %uninit = alloca %struct.virtualderived, align +// CHECK-NEXT: call void @{{.*}}virtualderived{{.*}}%uninit) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_virtualderived_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_virtualderived_uninit.uninit +// ZERO-LABEL: @test_virtualderived_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(virtualderived, virtualderived); +// CHECK-LABEL: @test_virtualderived_braces() +// CHECK: %braces = alloca %struct.virtualderived, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 16, i1 false) +// CHECK-NEXT: call void @{{.*}}virtualderived{{.*}}%braces) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + + +TEST_UNINIT(matching, matching); +// CHECK-LABEL: @test_matching_uninit() +// CHECK: %uninit = alloca %union.matching, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_matching_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_matching_uninit.uninit +// ZERO-LABEL: @test_matching_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(matching, matching); +// CHECK-LABEL: @test_matching_braces() +// CHECK: %braces = alloca %union.matching, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(matching, matching, { .f = 0xf00f }); +// CHECK-LABEL: @test_matching_custom() +// CHECK: %custom = alloca %union.matching, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(matchingreverse, matchingreverse); +// CHECK-LABEL: @test_matchingreverse_uninit() +// CHECK: %uninit = alloca %union.matchingreverse, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_matchingreverse_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_matchingreverse_uninit.uninit +// ZERO-LABEL: @test_matchingreverse_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(matchingreverse, matchingreverse); +// CHECK-LABEL: @test_matchingreverse_braces() +// CHECK: %braces = alloca %union.matchingreverse, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(matchingreverse, matchingreverse, { .i = 0xf00f }); +// CHECK-LABEL: @test_matchingreverse_custom() +// CHECK: %custom = alloca %union.matchingreverse, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(unmatched, unmatched); +// CHECK-LABEL: @test_unmatched_uninit() +// CHECK: %uninit = alloca %union.unmatched, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_unmatched_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatched_uninit.uninit +// ZERO-LABEL: @test_unmatched_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(unmatched, unmatched); +// CHECK-LABEL: @test_unmatched_braces() +// CHECK: %braces = alloca %union.unmatched, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(unmatched, unmatched, { .i = 0x3badbeef }); +// CHECK-LABEL: @test_unmatched_custom() +// CHECK: %custom = alloca %union.unmatched, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(unmatchedreverse, unmatchedreverse); +// CHECK-LABEL: @test_unmatchedreverse_uninit() +// CHECK: %uninit = alloca %union.unmatchedreverse, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_unmatchedreverse_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatchedreverse_uninit.uninit +// ZERO-LABEL: @test_unmatchedreverse_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(unmatchedreverse, unmatchedreverse); +// CHECK-LABEL: @test_unmatchedreverse_braces() +// CHECK: %braces = alloca %union.unmatchedreverse, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false) +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(unmatchedreverse, unmatchedreverse, { .c = 42 }); +// CHECK-LABEL: @test_unmatchedreverse_custom() +// CHECK: %custom = alloca %union.unmatchedreverse, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(unmatchedfp, unmatchedfp); +// CHECK-LABEL: @test_unmatchedfp_uninit() +// CHECK: %uninit = alloca %union.unmatchedfp, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_unmatchedfp_uninit() +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatchedfp_uninit.uninit +// ZERO-LABEL: @test_unmatchedfp_uninit() +// ZERO: call void @llvm.memset{{.*}}, i8 0, + +TEST_BRACES(unmatchedfp, unmatchedfp); +// CHECK-LABEL: @test_unmatchedfp_braces() +// CHECK: %braces = alloca %union.unmatchedfp, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(unmatchedfp, unmatchedfp, { .d = 3.1415926535897932384626433 }); +// CHECK-LABEL: @test_unmatchedfp_custom() +// CHECK: %custom = alloca %union.unmatchedfp, align +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @llvm.memcpy +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(emptyenum, emptyenum); +// CHECK-LABEL: @test_emptyenum_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_emptyenum_uninit() +// PATTERN: store i32 -1431655766, i32* %braces, align 4 +// ZERO-LABEL: @test_emptyenum_uninit() +// ZERO: store i32 0, i32* %braces, align 4 + +TEST_BRACES(emptyenum, emptyenum); +// CHECK-LABEL: @test_emptyenum_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(emptyenum, emptyenum, { (emptyenum)42 }); +// CHECK-LABEL: @test_emptyenum_custom() +// CHECK: %custom = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 42, i32* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(smallenum, smallenum); +// CHECK-LABEL: @test_smallenum_uninit() +// CHECK: %uninit = alloca i32, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_smallenum_uninit() +// PATTERN: store i32 -1431655766, i32* %braces, align 4 +// ZERO-LABEL: @test_smallenum_uninit() +// ZERO: store i32 0, i32* %braces, align 4 + +TEST_BRACES(smallenum, smallenum); +// CHECK-LABEL: @test_smallenum_braces() +// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(smallenum, smallenum, { (smallenum)42 }); +// CHECK-LABEL: @test_smallenum_custom() +// CHECK: %custom = alloca i32, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store i32 42, i32* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +TEST_UNINIT(intvec16, int __attribute__((vector_size(16)))); +// CHECK-LABEL: @test_intvec16_uninit() +// CHECK: %uninit = alloca <4 x i32>, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_intvec16_uninit() +// PATTERN: store <4 x i32> <i32 -1431655766, i32 -1431655766, i32 -1431655766, i32 -1431655766>, <4 x i32>* %uninit, align 16 +// ZERO-LABEL: @test_intvec16_uninit() +// ZERO: store <4 x i32> zeroinitializer, <4 x i32>* %uninit, align 16 + +TEST_BRACES(intvec16, int __attribute__((vector_size(16)))); +// CHECK-LABEL: @test_intvec16_braces() +// CHECK: %braces = alloca <4 x i32>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x i32> zeroinitializer, <4 x i32>* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(intvec16, int __attribute__((vector_size(16))), { 0x44444444, 0x44444444, 0x44444444, 0x44444444 }); +// CHECK-LABEL: @test_intvec16_custom() +// CHECK: %custom = alloca <4 x i32>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x i32> <i32 1145324612, i32 1145324612, i32 1145324612, i32 1145324612>, <4 x i32>* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(longlongvec32, long long __attribute__((vector_size(32)))); +// CHECK-LABEL: @test_longlongvec32_uninit() +// CHECK: %uninit = alloca <4 x i64>, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_longlongvec32_uninit() +// PATTERN: store <4 x i64> <i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206>, <4 x i64>* %uninit, align 32 +// ZERO-LABEL: @test_longlongvec32_uninit() +// ZERO: store <4 x i64> zeroinitializer, <4 x i64>* %uninit, align 32 + +TEST_BRACES(longlongvec32, long long __attribute__((vector_size(32)))); +// CHECK-LABEL: @test_longlongvec32_braces() +// CHECK: %braces = alloca <4 x i64>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x i64> zeroinitializer, <4 x i64>* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(longlongvec32, long long __attribute__((vector_size(32))), { 0x3333333333333333, 0x3333333333333333, 0x3333333333333333, 0x3333333333333333 }); +// CHECK-LABEL: @test_longlongvec32_custom() +// CHECK: %custom = alloca <4 x i64>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x i64> <i64 3689348814741910323, i64 3689348814741910323, i64 3689348814741910323, i64 3689348814741910323>, <4 x i64>* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(floatvec16, float __attribute__((vector_size(16)))); +// CHECK-LABEL: @test_floatvec16_uninit() +// CHECK: %uninit = alloca <4 x float>, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_floatvec16_uninit() +// PATTERN: store <4 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000>, <4 x float>* %uninit, align 16 +// ZERO-LABEL: @test_floatvec16_uninit() +// ZERO: store <4 x float> zeroinitializer, <4 x float>* %uninit, align 16 + +TEST_BRACES(floatvec16, float __attribute__((vector_size(16)))); +// CHECK-LABEL: @test_floatvec16_braces() +// CHECK: %braces = alloca <4 x float>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x float> zeroinitializer, <4 x float>* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(floatvec16, float __attribute__((vector_size(16))), { 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433 }); +// CHECK-LABEL: @test_floatvec16_custom() +// CHECK: %custom = alloca <4 x float>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x float> <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>, <4 x float>* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + +TEST_UNINIT(doublevec32, double __attribute__((vector_size(32)))); +// CHECK-LABEL: @test_doublevec32_uninit() +// CHECK: %uninit = alloca <4 x double>, align +// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) +// PATTERN-LABEL: @test_doublevec32_uninit() +// PATTERN: store <4 x double> <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>, <4 x double>* %uninit, align 32 +// ZERO-LABEL: @test_doublevec32_uninit() +// ZERO: store <4 x double> zeroinitializer, <4 x double>* %uninit, align 32 + +TEST_BRACES(doublevec32, double __attribute__((vector_size(32)))); +// CHECK-LABEL: @test_doublevec32_braces() +// CHECK: %braces = alloca <4 x double>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x double> zeroinitializer, <4 x double>* %braces, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces) + +TEST_CUSTOM(doublevec32, double __attribute__((vector_size(32))), { 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433 }); +// CHECK-LABEL: @test_doublevec32_custom() +// CHECK: %custom = alloca <4 x double>, align [[ALIGN:[0-9]*]] +// CHECK-NEXT: store <4 x double> <double 0x400921FB54442D18, double 0x400921FB54442D18, double 0x400921FB54442D18, double 0x400921FB54442D18>, <4 x double>* %custom, align [[ALIGN]] +// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom) + + +} // extern "C" diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp index ce1ebd615ef8..6aca809c2c72 100644 --- a/test/CodeGenCXX/block-byref-cxx-objc.cpp +++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp @@ -1,17 +1,23 @@ -// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -fblocks | FileCheck %s +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - -fblocks -fexceptions | FileCheck %s // rdar://8594790 struct A { int x; A(const A &); A(); - ~A(); + ~A() noexcept(false); }; -int main() -{ - __block A BYREF_VAR; - ^{ BYREF_VAR.x = 1234; }; +struct B { + int x; + B(const B &); + B(); + ~B(); +}; + +int testA() { + __block A a0, a1; + ^{ a0.x = 1234; a1.x = 5678; }; return 0; } @@ -19,10 +25,32 @@ int main() // CHECK: call {{.*}} @_ZN1AC1ERKS_ // CHECK-LABEL: define internal void @__Block_byref_object_dispose_ // CHECK: call {{.*}} @_ZN1AD1Ev -// CHECK-LABEL: define internal void @__copy_helper_block_ -// CHECK: call {{.*}}void @_Block_object_assign -// CHECK-LABEL: define internal void @__destroy_helper_block_ -// CHECK: call {{.*}}void @_Block_object_dispose + +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_e{{4|8}}_{{20|32}}rc{{24|40}}rc( +// CHECK: call void @_Block_object_assign( +// CHECK: invoke void @_Block_object_assign( +// CHECK: call void @_Block_object_dispose({{.*}}) #[[NOUNWIND_ATTR:[0-9]+]] + +// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_e{{4|8}}_{{20|32}}rd{{24|40}}rd( +// CHECK: invoke void @_Block_object_dispose( +// CHECK: call void @_Block_object_dispose( +// CHECK: invoke void @_Block_object_dispose( + +int testB() { + __block B b0, b1; + ^{ b0.x = 1234; b1.x = 5678; }; + return 0; +} + +// CHECK-LABEL: define internal void @__Block_byref_object_copy_ +// CHECK: call {{.*}} @_ZN1BC1ERKS_ +// CHECK-LABEL: define internal void @__Block_byref_object_dispose_ +// CHECK: call {{.*}} @_ZN1BD1Ev + +// CHECK-NOT: define{{.*}}@__copy_helper_block +// CHECK: define linkonce_odr hidden void @__destroy_helper_block_e{{4|8}}_{{20|32}}r{{24|40}}r( + +// CHECK: attributes #[[NOUNWIND_ATTR]] = {{{.*}}nounwind{{.*}}} // rdar://problem/11135650 namespace test1 { diff --git a/test/CodeGenCXX/block-byref.cpp b/test/CodeGenCXX/block-byref.cpp new file mode 100644 index 000000000000..1cb86a547573 --- /dev/null +++ b/test/CodeGenCXX/block-byref.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - | FileCheck %s +// REQUIRES: x86-registered-target + +// CHECK: @b = global i32 0, + +// CHECK: define {{.*}}void @{{.*}}test{{.*}}_block_invoke( +// CHECK: store i32 2, i32* @b, +// CHECK: ret void + +int b; + +void test() { + int &a = b; + ^{ a = 2; }; +} diff --git a/test/CodeGenCXX/block-capture.cpp b/test/CodeGenCXX/block-capture.cpp index 623838357a38..515d64d35dad 100644 --- a/test/CodeGenCXX/block-capture.cpp +++ b/test/CodeGenCXX/block-capture.cpp @@ -4,10 +4,12 @@ // CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz // CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1 // CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]] +// CHECK: bitcast %struct.__block_byref_baz* [[baz]] to i8* // CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8* // CHECK: call void @_Block_object_dispose(i8* [[disposable]] int main() { __block int baz = [&]() { return 0; }(); + ^{ (void)baz; }; return 0; } diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp index 37219d3f7abd..3b3363dc4175 100644 --- a/test/CodeGenCXX/blocks.cpp +++ b/test/CodeGenCXX/blocks.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } +// CHECK: @[[BLOCK_DESCRIPTOR22:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 36, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 8 + namespace test0 { // CHECK-LABEL: define void @_ZN5test04testEi( // CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}( @@ -73,6 +76,7 @@ namespace test2 { void test() { __block A a; __block B b; + ^{ (void)a; (void)b; }; } // CHECK-LABEL: define internal void @__Block_byref_object_copy @@ -122,7 +126,7 @@ namespace test4 { // CHECK-LABEL: define internal void @___ZN5test44testEv_block_invoke // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1 // CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8 - // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>* + // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]* }>* // CHECK: call void @_ZN5test41AC1Ev([[A]]* [[TMP]]) // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]]) // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]]) @@ -252,3 +256,54 @@ namespace test9 { }); } } + +namespace test10 { + // Check that 'v' is included in the copy helper function name to indicate + // the constructor taking a volatile parameter is called to copy the captured + // object. + + // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32c16_ZTSVN6test101BE( + // CHECK: call void @_ZN6test101BC1ERVKS0_( + // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32c16_ZTSVN6test101BE( + // CHECK: call void @_ZN6test101BD1Ev( + + struct B { + int a; + B(); + B(const B &); + B(const volatile B &); + ~B(); + }; + + void test() { + volatile B x; + ^{ (void)x; }; + } +} + +// Copy/dispose helper functions and block descriptors of blocks that capture +// objects that are non-external and non-trivial have internal linkage. + +// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_14testEv( +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR22]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %{{.*}}, align 8 + +// CHECK-LABEL: define internal void @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE( +// CHECK-LABEL: define internal void @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE( + +namespace { + struct B { + int a; + B(); + B(const B &); + ~B(); + }; + + void test() { + B x; + ^{ (void)x; }; + } +} + +void callTest() { + test(); +} diff --git a/test/CodeGenCXX/builtin-constant-p.cpp b/test/CodeGenCXX/builtin-constant-p.cpp new file mode 100644 index 000000000000..6d853e8a6828 --- /dev/null +++ b/test/CodeGenCXX/builtin-constant-p.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s + +// Don't crash if the argument to __builtin_constant_p isn't scalar. +template <typename T> +constexpr bool is_constant(const T v) { + return __builtin_constant_p(v); +} + +template <typename T> +class numeric { + public: + using type = T; + + template <typename S> + constexpr numeric(S value) + : value_(static_cast<T>(value)) {} + + private: + const T value_; +}; + +bool bcp() { + return is_constant(numeric<int>(1)); +} diff --git a/test/CodeGenCXX/builtin-launder.cpp b/test/CodeGenCXX/builtin-launder.cpp new file mode 100644 index 000000000000..b3d849c8aec9 --- /dev/null +++ b/test/CodeGenCXX/builtin-launder.cpp @@ -0,0 +1,321 @@ +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fstrict-vtable-pointers -o - %s \ +// RUN: | FileCheck --check-prefixes=CHECK,CHECK-STRICT %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes=CHECK,CHECK-NONSTRICT %s + +//===----------------------------------------------------------------------===// +// Positive Cases +//===----------------------------------------------------------------------===// + +struct TestVirtualFn { + virtual void foo() {} +}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_fn +extern "C" void test_builtin_launder_virtual_fn(TestVirtualFn *p) { + // CHECK: store [[TYPE:%[^ ]+]] %p, [[TYPE]]* %p.addr + // CHECK-NEXT: [[TMP0:%.*]] = load [[TYPE]], [[TYPE]]* %p.addr + + // CHECK-NONSTRICT-NEXT: store [[TYPE]] [[TMP0]], [[TYPE]]* %d + + // CHECK-STRICT-NEXT: [[TMP1:%.*]] = bitcast [[TYPE]] [[TMP0]] to i8* + // CHECK-STRICT-NEXT: [[TMP2:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[TMP1]]) + // CHECK-STRICT-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to [[TYPE]] + // CHECK-STRICT-NEXT: store [[TYPE]] [[TMP3]], [[TYPE]]* %d + + // CHECK-NEXT: ret void + TestVirtualFn *d = __builtin_launder(p); +} + +struct TestPolyBase : TestVirtualFn { +}; + +// CHECK-LABEL: define void @test_builtin_launder_poly_base +extern "C" void test_builtin_launder_poly_base(TestPolyBase *p) { + // CHECK-STRICT-NOT: ret void + // CHECK-STRICT: @llvm.launder.invariant.group + + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + + // CHECK: ret void + TestPolyBase *d = __builtin_launder(p); +} + +struct TestBase {}; +struct TestVirtualBase : virtual TestBase {}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_base +extern "C" void test_builtin_launder_virtual_base(TestVirtualBase *p) { + // CHECK-STRICT-NOT: ret void + // CHECK-STRICT: @llvm.launder.invariant.group + + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + + // CHECK: ret void + TestVirtualBase *d = __builtin_launder(p); +} + +//===----------------------------------------------------------------------===// +// Negative Cases +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: define void @test_builtin_launder_ommitted_one +extern "C" void test_builtin_launder_ommitted_one(int *p) { + // CHECK: entry + // CHECK-NEXT: %p.addr = alloca i32* + // CHECK-NEXT: %d = alloca i32* + // CHECK-NEXT: store i32* %p, i32** %p.addr, align 8 + // CHECK-NEXT: [[TMP:%.*]] = load i32*, i32** %p.addr + // CHECK-NEXT: store i32* [[TMP]], i32** %d + // CHECK-NEXT: ret void + int *d = __builtin_launder(p); +} + +struct TestNoInvariant { + int x; +}; + +// CHECK-LABEL: define void @test_builtin_launder_ommitted_two +extern "C" void test_builtin_launder_ommitted_two(TestNoInvariant *p) { + // CHECK: entry + // CHECK-NOT: llvm.launder.invariant.group + // CHECK-NEXT: %p.addr = alloca [[TYPE:%.*]], align 8 + // CHECK-NEXT: %d = alloca [[TYPE]] + // CHECK-NEXT: store [[TYPE]] %p, [[TYPE]]* %p.addr + // CHECK-NEXT: [[TMP:%.*]] = load [[TYPE]], [[TYPE]]* %p.addr + // CHECK-NEXT: store [[TYPE]] [[TMP]], [[TYPE]]* %d + // CHECK-NEXT: ret void + TestNoInvariant *d = __builtin_launder(p); +} + +struct TestVirtualMember { + TestVirtualFn member; +}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_member +extern "C" void test_builtin_launder_virtual_member(TestVirtualMember *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + TestVirtualMember *d = __builtin_launder(p); +} + +struct TestVirtualMemberDepth2 { + TestVirtualMember member; +}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_member_depth_2 +extern "C" void test_builtin_launder_virtual_member_depth_2(TestVirtualMemberDepth2 *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + TestVirtualMemberDepth2 *d = __builtin_launder(p); +} + +struct TestVirtualReferenceMember { + TestVirtualFn &member; +}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_reference_member +extern "C" void test_builtin_launder_virtual_reference_member(TestVirtualReferenceMember *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestVirtualReferenceMember *d = __builtin_launder(p); +} + +struct TestRecursiveMember { + TestRecursiveMember() : member(*this) {} + TestRecursiveMember &member; +}; + +// CHECK-LABEL: define void @test_builtin_launder_recursive_member +extern "C" void test_builtin_launder_recursive_member(TestRecursiveMember *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestRecursiveMember *d = __builtin_launder(p); +} + +struct TestVirtualRecursiveMember { + TestVirtualRecursiveMember() : member(*this) {} + TestVirtualRecursiveMember &member; + virtual void foo(); +}; + +// CHECK-LABEL: define void @test_builtin_launder_virtual_recursive_member +extern "C" void test_builtin_launder_virtual_recursive_member(TestVirtualRecursiveMember *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + TestVirtualRecursiveMember *d = __builtin_launder(p); +} + +// CHECK-LABEL: define void @test_builtin_launder_array( +extern "C" void test_builtin_launder_array(TestVirtualFn (&Arr)[5]) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + TestVirtualFn *d = __builtin_launder(Arr); +} + +// CHECK-LABEL: define void @test_builtin_launder_array_nested( +extern "C" void test_builtin_launder_array_nested(TestVirtualFn (&Arr)[5][2]) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + using RetTy = TestVirtualFn(*)[2]; + RetTy d = __builtin_launder(Arr); +} + +// CHECK-LABEL: define void @test_builtin_launder_array_no_invariant( +extern "C" void test_builtin_launder_array_no_invariant(TestNoInvariant (&Arr)[5]) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestNoInvariant *d = __builtin_launder(Arr); +} + +// CHECK-LABEL: define void @test_builtin_launder_array_nested_no_invariant( +extern "C" void test_builtin_launder_array_nested_no_invariant(TestNoInvariant (&Arr)[5][2]) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + using RetTy = TestNoInvariant(*)[2]; + RetTy d = __builtin_launder(Arr); +} + +template <class Member> +struct WithMember { + Member mem; +}; + +template struct WithMember<TestVirtualFn[5]>; + +// CHECK-LABEL: define void @test_builtin_launder_member_array( +extern "C" void test_builtin_launder_member_array(WithMember<TestVirtualFn[5]> *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +template struct WithMember<TestVirtualFn[5][2]>; + +// CHECK-LABEL: define void @test_builtin_launder_member_array_nested( +extern "C" void test_builtin_launder_member_array_nested(WithMember<TestVirtualFn[5][2]> *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +template struct WithMember<TestNoInvariant[5]>; + +// CHECK-LABEL: define void @test_builtin_launder_member_array_no_invariant( +extern "C" void test_builtin_launder_member_array_no_invariant(WithMember<TestNoInvariant[5]> *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +template struct WithMember<TestNoInvariant[5][2]>; + +// CHECK-LABEL: define void @test_builtin_launder_member_array_nested_no_invariant( +extern "C" void test_builtin_launder_member_array_nested_no_invariant(WithMember<TestNoInvariant[5][2]> *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +template <class T> +struct WithBase : T {}; + +template struct WithBase<TestNoInvariant>; + +// CHECK-LABEL: define void @test_builtin_launder_base_no_invariant( +extern "C" void test_builtin_launder_base_no_invariant(WithBase<TestNoInvariant> *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +template struct WithBase<TestVirtualFn>; + +// CHECK-LABEL: define void @test_builtin_launder_base( +extern "C" void test_builtin_launder_base(WithBase<TestVirtualFn> *p) { + // CHECK: entry + // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group + // CHECK-STRICT: @llvm.launder.invariant.group + // CHECK: ret void + auto *d = __builtin_launder(p); +} + +/// The test cases in this namespace technically need to be laundered according +/// to the language in the standard (ie they have const or reference subobjects) +/// but LLVM doesn't currently optimize on these cases -- so Clang emits +/// __builtin_launder as a nop. +/// +/// NOTE: Adding optimizations for these cases later is an LTO ABI break. That's +/// probably OK for now -- but is something to keep in mind. +namespace pessimizing_cases { + +struct TestConstMember { + const int x; +}; + +// CHECK-LABEL: define void @test_builtin_launder_const_member +extern "C" void test_builtin_launder_const_member(TestConstMember *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestConstMember *d = __builtin_launder(p); +} + +struct TestConstSubobject { + TestConstMember x; +}; + +// CHECK-LABEL: define void @test_builtin_launder_const_subobject +extern "C" void test_builtin_launder_const_subobject(TestConstSubobject *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestConstSubobject *d = __builtin_launder(p); +} + +struct TestConstObject { + const struct TestConstMember x; +}; + +// CHECK-LABEL: define void @test_builtin_launder_const_object +extern "C" void test_builtin_launder_const_object(TestConstObject *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestConstObject *d = __builtin_launder(p); +} + +struct TestReferenceMember { + int &x; +}; + +// CHECK-LABEL: define void @test_builtin_launder_reference_member +extern "C" void test_builtin_launder_reference_member(TestReferenceMember *p) { + // CHECK: entry + // CHECK-NOT: @llvm.launder.invariant.group + // CHECK: ret void + TestReferenceMember *d = __builtin_launder(p); +} + +} // namespace pessimizing_cases diff --git a/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp b/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp index d5c1f603ff3f..61272b1ceea2 100644 --- a/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp +++ b/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp @@ -1,8 +1,12 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - +// RUN: %clang_cc1 %s -emit-llvm-only -o - // https://bugs.llvm.org/show_bug.cgi?id=38356 // We only check that we do not crash. +// ASAN increases stack usage, so we are hitting stack overflow before reaching +// recursive template instantiation limit. +// XFAIL: darwin && asan + template <typename a, a b(unsigned), int c, unsigned...> struct d : d<a, b, c - 1> {}; template <typename a, a b(unsigned), unsigned... e> diff --git a/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp b/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp new file mode 100644 index 000000000000..95349387b3b4 --- /dev/null +++ b/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER +// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER +// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP + +extern "C" { // Disable name mangling. + +// ========================================================================== // +// The expected true-negatives. +// ========================================================================== // + +// Sanitization is explicitly disabled. +// ========================================================================== // + +// CHECK-LABEL: @blacklist_0 +__attribute__((no_sanitize("undefined"))) unsigned int blacklist_0(signed int src) { + // We are not in "undefined" group, so that doesn't work. + // CHECK-SANITIZE: call + // CHECK: } + return src; +} + +// CHECK-LABEL: @blacklist_1 +__attribute__((no_sanitize("integer"))) unsigned int blacklist_1(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return src; +} + +// CHECK-LABEL: @blacklist_2 +__attribute__((no_sanitize("implicit-conversion"))) unsigned int blacklist_2(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return src; +} + +// CHECK-LABEL: @blacklist_3 +__attribute__((no_sanitize("implicit-integer-sign-change"))) unsigned int blacklist_3(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return src; +} + +// Explicit sign-changing conversions. +// ========================================================================== // + +// CHECK-LABEL: @explicit_signed_int_to_unsigned_int +unsigned int explicit_signed_int_to_unsigned_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return (unsigned int)src; +} + +// CHECK-LABEL: @explicit_unsigned_int_to_signed_int +signed int explicit_unsigned_int_to_signed_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return (signed int)src; +} + +// Explicit NOP conversions. +// ========================================================================== // + +// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int +unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return (unsigned int)src; +} + +// CHECK-LABEL: @explicit_signed_int_to_signed_int +signed int explicit_signed_int_to_signed_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return (signed int)src; +} + +// Explicit functional sign-changing casts. +// ========================================================================== // + +using UnsignedInt = unsigned int; +using SignedInt = signed int; + +// CHECK-LABEL: explicit_functional_unsigned_int_to_signed_int +signed int explicit_functional_unsigned_int_to_signed_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return SignedInt(src); +} + +// CHECK-LABEL: @explicit_functional_signed_int_to_unsigned_int +unsigned int explicit_functional_signed_int_to_unsigned_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return UnsignedInt(src); +} + +// Explicit functional NOP casts. +// ========================================================================== // + +// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_int +unsigned int explicit_functional_unsigned_int_to_unsigned_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return UnsignedInt(src); +} + +// CHECK-LABEL: @explicit_functional_signed_int_to_signed_int +signed int explicit_functional_signed_int_to_signed_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return SignedInt(src); +} + +// Explicit C++-style sign-changing casts. +// ========================================================================== // + +// CHECK-LABEL: @explicit_cppstyle_unsigned_int_to_signed_int +signed int explicit_cppstyle_unsigned_int_to_signed_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return static_cast<signed int>(src); +} + +// CHECK-LABEL: @explicit_cppstyle_signed_int_to_unsigned_int +unsigned int explicit_cppstyle_signed_int_to_unsigned_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return static_cast<unsigned int>(src); +} + +// Explicit C++-style casts NOP casts. +// ========================================================================== // + +// CHECK-LABEL: @explicit_cppstyle_unsigned_int_to_unsigned_int +unsigned int explicit_cppstyle_unsigned_int_to_unsigned_int(unsigned int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return static_cast<unsigned int>(src); +} + +// CHECK-LABEL: @explicit_cppstyle_signed_int_to_signed_int +signed int explicit_cppstyle_signed_int_to_signed_int(signed int src) { + // CHECK-SANITIZE-NOT: call + // CHECK: } + return static_cast<signed int>(src); +} + +} // extern "C" diff --git a/test/CodeGenCXX/catch-implicit-integer-truncations.cpp b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp index ba7676a3504a..2902fe1e884d 100644 --- a/test/CodeGenCXX/catch-implicit-integer-truncations.cpp +++ b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK -// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER -// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER -// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP +// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER +// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER +// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP extern "C" { // Disable name mangling. diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index 4513936e49a3..0e8d4fa51a0c 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -72,7 +72,7 @@ void member_access(S *p) { // The two hash values are for 64- and 32-bit Clang binaries, respectively. // FIXME: We should produce a 64-bit value either way. // - // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}}, %[[VPTR]] + // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}}, %[[VPTR]] // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023 // CHECK-NEXT: lshr i64 {{.*}}, 47 // CHECK-NEXT: xor i64 @@ -121,7 +121,7 @@ void member_access(S *p) { // (3b) Check that 'p' actually points to an 'S' // CHECK: load i64, i64* - // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}}, + // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}}, // [...] // CHECK: getelementptr inbounds [128 x i64], [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 % // CHECK: br i1 @@ -520,6 +520,49 @@ void upcast_to_vbase() { } } +struct nothrow {}; +void *operator new[](__SIZE_TYPE__, nothrow) noexcept; + +namespace NothrowNew { + struct X { X(); }; + + // CHECK-LABEL: define{{.*}}nothrow_new_trivial + void *nothrow_new_trivial() { + // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null + // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] + + // CHECK: [[nonnull]]: + // CHECK: llvm.objectsize + // CHECK: br i1 + // + // CHECK: call {{.*}}__ubsan_handle_type_mismatch + // + // CHECK: [[null]]: + // CHECK-NOT: {{ }}br{{ }} + // CHECK: ret + return new (nothrow{}) char[123456]; + } + + // CHECK-LABEL: define{{.*}}nothrow_new_nontrivial + void *nothrow_new_nontrivial() { + // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null + // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] + + // CHECK: [[nonnull]]: + // CHECK: llvm.objectsize + // CHECK: br i1 + // + // CHECK: call {{.*}}__ubsan_handle_type_mismatch + // + // CHECK: call {{.*}}_ZN10NothrowNew1XC1Ev + // + // CHECK: [[null]]: + // CHECK-NOT: {{ }}br{{ }} + // CHECK: ret + return new (nothrow{}) X[123456]; + } +} + struct ThisAlign { void this_align_lambda(); void this_align_lambda_2(); diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp index 6d5e0591191c..4b7b3d70f098 100644 --- a/test/CodeGenCXX/cfi-cross-dso.cpp +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -26,7 +26,7 @@ void g() { b.f(); } -// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ" +// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A0x{{[^@]*}}@@6B@"{{.*}}@"?f@B@?A0x{{[^@]*}}@@UEAAXXZ" // CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)*** // CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp index e53aeefd8a9b..00c9f59700ac 100644 --- a/test/CodeGenCXX/cfi-icall.cpp +++ b/test/CodeGenCXX/cfi-icall.cpp @@ -21,7 +21,7 @@ void g() { } // ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] -// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] +// MS: define internal void @"?f@?A0x{{[^@]*}}@@YAXUS@?A0x{{[^@]*}}@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] // CHECK: [[VOIDS1]] = distinct !{} // CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]} diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp index e08de61f9d41..48c911788265 100644 --- a/test/CodeGenCXX/conditional-temporaries.cpp +++ b/test/CodeGenCXX/conditional-temporaries.cpp @@ -1,6 +1,7 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O3 | FileCheck %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O3 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT namespace { @@ -38,20 +39,167 @@ Checker c; } -// CHECK-LABEL: define i32 @_Z12getCtorCallsv() +// CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv() int getCtorCalls() { - // CHECK: ret i32 5 + // CHECK-OPT: ret i32 5 return ctorcalls; } -// CHECK-LABEL: define i32 @_Z12getDtorCallsv() +// CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv() int getDtorCalls() { - // CHECK: ret i32 5 + // CHECK-OPT: ret i32 5 return dtorcalls; } -// CHECK-LABEL: define zeroext i1 @_Z7successv() +// CHECK-OPT-LABEL: define zeroext i1 @_Z7successv() bool success() { - // CHECK: ret i1 true + // CHECK-OPT: ret i1 true return ctorcalls == dtorcalls; } + +struct X { ~X(); int f(); }; +int g(int, int, int); +// CHECK-LABEL: @_Z16lifetime_nontriv +int lifetime_nontriv(bool cond) { + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: store i1 false, + // CHECK-NOOPT: br i1 + // + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: call i32 @_ZN1X1fEv( + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: call i32 @_ZN1X1fEv( + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: store i1 true, + // CHECK-NOOPT: call i32 @_ZN1X1fEv( + // CHECK-NOOPT: call i32 @_Z1giii( + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @_ZN1XD1Ev( + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @llvm.lifetime.end + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @_ZN1XD1Ev( + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @llvm.lifetime.end + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @_ZN1XD1Ev( + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: load i1, + // CHECK-NOOPT: br i1 + // CHECK-NOOPT: call void @llvm.lifetime.end + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: ret + + // CHECK-OPT: br i1 + // + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1X1fEv( + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1X1fEv( + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1X1fEv( + // CHECK-OPT: call i32 @_Z1giii( + // CHECK-OPT: call void @_ZN1XD1Ev( + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @_ZN1XD1Ev( + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @_ZN1XD1Ev( + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: br label + return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3); +} + +struct Y { int f(); }; +int g(int, int, int); +// CHECK-LABEL: @_Z13lifetime_triv +int lifetime_triv(bool cond) { + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: call void @llvm.lifetime.start + // CHECK-NOOPT: br i1 + // + // CHECK-NOOPT: call i32 @_ZN1Y1fEv( + // CHECK-NOOPT: call i32 @_ZN1Y1fEv( + // CHECK-NOOPT: call i32 @_ZN1Y1fEv( + // CHECK-NOOPT: call i32 @_Z1giii( + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3) + // CHECK-NOOPT: br label + // + // CHECK-NOOPT: call void @llvm.lifetime.end + // CHECK-NOOPT-NOT: br + // CHECK-NOOPT: call void @llvm.lifetime.end + // CHECK-NOOPT-NOT: br + // CHECK-NOOPT: call void @llvm.lifetime.end + // + // CHECK-NOOPT: ret + + // FIXME: LLVM isn't smart enough to remove the lifetime markers from the + // g(1, 2, 3) path here. + + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: br i1 + // + // CHECK-OPT: call i32 @_ZN1Y1fEv( + // CHECK-OPT: call i32 @_ZN1Y1fEv( + // CHECK-OPT: call i32 @_ZN1Y1fEv( + // CHECK-OPT: call i32 @_Z1giii( + // CHECK-OPT: br label + // + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @llvm.lifetime.end + return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3); +} + +struct Z { ~Z() {} int f(); }; +int g(int, int, int); +// CHECK-LABEL: @_Z22lifetime_nontriv_empty +int lifetime_nontriv_empty(bool cond) { + // CHECK-OPT: br i1 + // + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1Z1fEv( + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1Z1fEv( + // CHECK-OPT: call void @llvm.lifetime.start + // CHECK-OPT: call i32 @_ZN1Z1fEv( + // CHECK-OPT: call i32 @_Z1giii( + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: call void @llvm.lifetime.end + // CHECK-OPT: br label + return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3); +} diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 801d7b1e19cc..9fb4ba5fe178 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -402,7 +402,7 @@ namespace UnemittedTemporaryDecl { // CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101 // CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102 -// CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103 +// CHECK: @__const._ZN12LocalVarInit8mutable_Ev.a = private unnamed_addr constant {{.*}} i32 103 // CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ = linkonce_odr constant i32 5, comdat // CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ // CHECK: @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ = linkonce_odr hidden constant i32 5, comdat @@ -461,7 +461,7 @@ namespace LocalVarInit { // CHECK: define {{.*}} @_ZN12LocalVarInit8mutable_Ev // CHECK-NOT: call - // CHECK: call {{.*}}memcpy{{.*}} @_ZZN12LocalVarInit8mutable_EvE1a + // CHECK: call {{.*}}memcpy{{.*}} @__const._ZN12LocalVarInit8mutable_Ev.a // CHECK-NOT: call // Can't fold return value due to 'mutable'. // CHECK-NOT: ret i32 103 diff --git a/test/CodeGenCXX/crash.cpp b/test/CodeGenCXX/crash.cpp index d12c021a6dcc..63bca484b5dd 100644 --- a/test/CodeGenCXX/crash.cpp +++ b/test/CodeGenCXX/crash.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only // RUN: %clang_cc1 -emit-obj -o %t -debug-info-kind=line-tables-only -std=c++11 %s +// RUN: %clang_cc1 -emit-obj -o %t -debug-info-kind=line-directives-only -std=c++11 %s // CHECK that we don't crash. // PR11676's example is ill-formed: diff --git a/test/CodeGenCXX/cxx-block-objects.cpp b/test/CodeGenCXX/cxx-block-objects.cpp index ff868fcdd06f..d28bcb670fd2 100644 --- a/test/CodeGenCXX/cxx-block-objects.cpp +++ b/test/CodeGenCXX/cxx-block-objects.cpp @@ -25,9 +25,9 @@ main() return 0; } -// CHECK-LABEL: define internal void @__copy_helper_block_ +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ // CHECK: call void @_ZN1AC1ERKS_ -// CHECK-LABEL:define internal void @__destroy_helper_block_ +// CHECK-LABEL:define linkonce_odr hidden void @__destroy_helper_block_ // CHECK: call void @_ZN1AD1Ev diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 70f5a47fd3b8..156c4f591908 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX --check-prefix=CHECK-OPT %s // RUN: %clang_cc1 -std=c++11 -femulated-tls -emit-llvm %s -o - \ // RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s @@ -307,6 +308,7 @@ void set_anon_i() { // CHECK: br i1 %[[NEED_TLS_INIT]], // init: // CHECK: store i8 1, i8* @__tls_guard +// CHECK-OPT: call {}* @llvm.invariant.start.p0i8(i64 1, i8* @__tls_guard) // CHECK-NOT: call void @[[V_M_INIT]]() // CHECK: call void @[[A_INIT]]() // CHECK-NOT: call void @[[V_M_INIT]]() diff --git a/test/CodeGenCXX/cxx1y-init-captures.cpp b/test/CodeGenCXX/cxx1y-init-captures.cpp index dcfe4d47292d..c76180c5bf43 100644 --- a/test/CodeGenCXX/cxx1y-init-captures.cpp +++ b/test/CodeGenCXX/cxx1y-init-captures.cpp @@ -38,6 +38,19 @@ void g() { // CHECK: add nsw i32 +// CHECK-LABEL: define void @_Z18init_capture_dtorsv +void init_capture_dtors() { + // Ensure that init-captures are not treated as separate full-expressions. + struct HasDtor { ~HasDtor() {} }; + void some_function_call(); + void other_function_call(); + // CHECK: call {{.*}}some_function_call + // CHECK: call {{.*}}HasDtorD + ([x = (HasDtor(), 0)]{}, some_function_call()); + // CHECK: call {{.*}}other_function_call + other_function_call(); +} + int h(int a) { // CHECK-LABEL: define i32 @_Z1hi( // CHECK: %[[A_ADDR:.*]] = alloca i32, diff --git a/test/CodeGenCXX/cxx2a-init-statement.cpp b/test/CodeGenCXX/cxx2a-init-statement.cpp new file mode 100644 index 000000000000..2d45c8554451 --- /dev/null +++ b/test/CodeGenCXX/cxx2a-init-statement.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++2a -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s + +// CHECK: @__const._Z1fv.arr = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 + +void f() { + // CHECK: %[[ARR:.*]] = alloca [3 x i32], align 4 + // CHECK: call void @llvm.memcpy{{.*}}({{.*}} @__const._Z1fv.arr + for (int arr[3] = {1, 2, 3}; int a : arr) + ; +} diff --git a/test/CodeGenCXX/dbg-info-all-calls-described.cpp b/test/CodeGenCXX/dbg-info-all-calls-described.cpp new file mode 100644 index 000000000000..547c2707226d --- /dev/null +++ b/test/CodeGenCXX/dbg-info-all-calls-described.cpp @@ -0,0 +1,61 @@ +// Test that call site debug info is (un)supported in various configurations. + +// Supported: DWARF5, -O1, standalone DI +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \ +// RUN: -O1 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=HAS-ATTR \ +// RUN: -implicit-check-not=DISubprogram -implicit-check-not=DIFlagAllCallsDescribed + +// Supported: DWARF4 + LLDB tuning, -O1, limited DI +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \ +// RUN: -O1 -disable-llvm-passes \ +// RUN: -debugger-tuning=lldb \ +// RUN: -debug-info-kind=standalone -dwarf-version=4 \ +// RUN: | FileCheck %s -check-prefix=HAS-ATTR \ +// RUN: -implicit-check-not=DISubprogram -implicit-check-not=DIFlagAllCallsDescribed + +// Supported: DWARF4 + LLDB tuning, -O1, line-tables only DI +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \ +// RUN: -O1 -disable-llvm-passes \ +// RUN: -debugger-tuning=lldb \ +// RUN: -debug-info-kind=line-tables-only -dwarf-version=4 \ +// RUN: | FileCheck %s -check-prefix=LINE-TABLES-ONLY + +// Unsupported: -O0 +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \ +// RUN: -O0 \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=NO-ATTR + +// Unsupported: DWARF4 +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \ +// RUN: -O1 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=4 \ +// RUN: | FileCheck %s -check-prefix=NO-ATTR + +// NO-ATTR-NOT: FlagAllCallsDescribed + +// HAS-ATTR-DAG: DISubprogram(name: "declaration2", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition +// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition +// HAS-ATTR-DAG: DISubprogram(name: "method1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition +// HAS-ATTR-DAG: DISubprogram(name: "force_irgen", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition + +// LINE-TABLES-ONLY: DISubprogram(name: "force_irgen", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition + +void declaration1(); + +void declaration2(); + +void declaration2() {} + +struct struct1 { + struct1() {} + void method1() {} +}; + +void __attribute__((optnone)) force_irgen() { + declaration1(); + struct1().method1(); +} diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp index 44d6b4da17a3..0759ee1d13bd 100644 --- a/test/CodeGenCXX/debug-info-access.cpp +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -35,8 +35,8 @@ private: // CHECK: !DISubprogram(name: "free", -// CHECK-SAME: isDefinition: true // CHECK-SAME: flags: DIFlagPrototyped, +// CHECK-SAME: spFlags: DISPFlagDefinition void free() {} U u; diff --git a/test/CodeGenCXX/debug-info-blocks.cpp b/test/CodeGenCXX/debug-info-blocks.cpp index ed0d659eeae1..7eea3ce09649 100644 --- a/test/CodeGenCXX/debug-info-blocks.cpp +++ b/test/CodeGenCXX/debug-info-blocks.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -debug-info-kind=line-tables-only -fblocks -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -debug-info-kind=line-directives-only -fblocks -S -emit-llvm -o - | FileCheck %s struct A { A(); @@ -8,11 +9,12 @@ struct A { void test() { __block A a; + ^{ (void)a; }; } // CHECK: !DISubprogram(name: "__Block_byref_object_copy_", -// CHECK-SAME: line: 10, -// CHECK-SAME: isLocal: true, isDefinition: true +// CHECK-SAME: line: 11, +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition // CHECK: !DISubprogram(name: "__Block_byref_object_dispose_", -// CHECK-SAME: line: 10, -// CHECK-SAME: isLocal: true, isDefinition: true +// CHECK-SAME: line: 11, +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp index 5b0850b9643c..38f803d6d9bb 100644 --- a/test/CodeGenCXX/debug-info-byval.cpp +++ b/test/CodeGenCXX/debug-info-byval.cpp @@ -1,5 +1,5 @@ // FIXME: Check IR rather than asm, then triple is not needed. -// RUN: %clang -Xclang -triple=%itanium_abi_triple -g -S %s -o - | FileCheck %s +// RUN: %clang --target=%itanium_abi_triple -g -S %s -o - | FileCheck %s // Test to check presence of debug info for byval parameter. // Radar 8350436. class DAG { diff --git a/test/CodeGenCXX/debug-info-class-limited-plugin.test b/test/CodeGenCXX/debug-info-class-limited-plugin.test index 533c2f6b16c5..17248d5743da 100644 --- a/test/CodeGenCXX/debug-info-class-limited-plugin.test +++ b/test/CodeGenCXX/debug-info-class-limited-plugin.test @@ -1,2 +1,2 @@ -RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp +RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-fns %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp REQUIRES: plugins, examples diff --git a/test/CodeGenCXX/debug-info-ctor2.cpp b/test/CodeGenCXX/debug-info-ctor2.cpp index 3bc931e98448..95b0608dadc8 100644 --- a/test/CodeGenCXX/debug-info-ctor2.cpp +++ b/test/CodeGenCXX/debug-info-ctor2.cpp @@ -1,5 +1,5 @@ // FIXME: Check IR rather than asm, then triple is not needed. -// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit +// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit class MyClass diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp index 403424e2d6a8..f1298b1d858c 100644 --- a/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -18,12 +18,12 @@ // FIXME: The context of this definition should be the CU/file scope, not the class. // CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]] // CHECK-SAME: type: [[SUBROUTINE_TYPE]] -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagDefinition // CHECK-SAME: declaration: [[FUNC_DECL:![0-9]*]] // CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func", // CHECK-SAME: scope: [[FOO]] // CHECK-SAME: type: [[SUBROUTINE_TYPE]] -// CHECK-SAME: isDefinition: false +// CHECK-SAME: spFlags: 0 struct foo { static auto func(); diff --git a/test/CodeGenCXX/debug-info-decl-nested.cpp b/test/CodeGenCXX/debug-info-decl-nested.cpp index feab1d709094..5345ff2dff94 100644 --- a/test/CodeGenCXX/debug-info-decl-nested.cpp +++ b/test/CodeGenCXX/debug-info-decl-nested.cpp @@ -19,13 +19,13 @@ class OuterClass } theInnerClass; // CHECK0: ![[DECL:[0-9]+]] = !DISubprogram(name: "OuterClass" // CHECK0-SAME: line: [[@LINE+2]] -// CHECK0-SAME: isDefinition: false +// CHECK0-SAME: spFlags: 0 OuterClass(const Foo *); // line 10 }; OuterClass::InnerClass OuterClass::theInnerClass; // This toplevel decl causes InnerClass to be generated. // CHECK0: !DISubprogram(name: "OuterClass" // CHECK0-SAME: line: [[@LINE+3]] -// CHECK0-SAME: isDefinition: true +// CHECK0-SAME: DISPFlagDefinition // CHECK0-SAME: declaration: ![[DECL]] OuterClass::OuterClass(const Foo *meta) { } // line 13 @@ -43,13 +43,13 @@ class OuterClass1 } theInnerClass1; // CHECK1: ![[DECL:[0-9]+]] = !DISubprogram(name: "Bar" // CHECK1-SAME: line: [[@LINE+2]] -// CHECK1-SAME: isDefinition: false +// CHECK1-SAME: spFlags: 0 void Bar(const Foo1 *); }; OuterClass1::InnerClass1 OuterClass1::theInnerClass1; // CHECK1: !DISubprogram(name: "Bar" // CHECK1-SAME: line: [[@LINE+3]] -// CHECK1-SAME: isDefinition: true +// CHECK1-SAME: DISPFlagDefinition // CHECK1-SAME: declaration: ![[DECL]] void OuterClass1::Bar(const Foo1 *meta) { } @@ -66,12 +66,12 @@ class OuterClass2 } theInnerClass2; // CHECK2: ![[DECL:[0-9]+]] = !DISubprogram(name: "~OuterClass2" // CHECK2-SAME: line: [[@LINE+2]] -// CHECK2-SAME: isDefinition: false +// CHECK2-SAME: spFlags: 0 ~OuterClass2(); // line 10 }; OuterClass2::InnerClass2 OuterClass2::theInnerClass2; // CHECK4: !DISubprogram(name: "~OuterClass2" // CHECK4-SAME: line: [[@LINE+3]] -// CHECK4-SAME: isDefinition: true +// CHECK4-SAME: DISPFlagDefinition // CHECK4-SAME: declaration: ![[DECL]] OuterClass2::~OuterClass2() { } diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index e857bb195913..3664c67bf360 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -15,7 +15,7 @@ D d; // CHECK-SAME: baseType: ![[INT:[0-9]+]] // CHECK-SAME: size: 32 // CHECK-NOT: offset: -// CHECK-SAME: flags: DIFlagFixedEnum +// CHECK-SAME: flags: DIFlagEnumClass // CHECK-SAME: ){{$}} // CHECK: ![[INT]] = !DIBasicType(name: "int" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B" @@ -23,7 +23,7 @@ D d; // CHECK-SAME: baseType: ![[ULONG:[0-9]+]] // CHECK-SAME: size: 64 // CHECK-NOT: offset: -// CHECK-SAME: flags: DIFlagFixedEnum +// CHECK-SAME: flags: DIFlagEnumClass // CHECK-SAME: ){{$}} // CHECK: ![[ULONG]] = !DIBasicType(name: "long unsigned int" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C" @@ -52,6 +52,7 @@ namespace test2 { // FIXME: this should just be a declaration under -fno-standalone-debug // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E" // CHECK-SAME: scope: [[TEST2:![0-9]+]] +// CHECK-NOT: DIFlagEnumClass // CHECK-SAME: elements: [[TEST_ENUMS:![0-9]+]] // CHECK-SAME: identifier: "_ZTSN5test21EE" // CHECK: [[TEST2]] = !DINamespace(name: "test2" @@ -67,6 +68,7 @@ namespace test3 { // FIXME: this should just be a declaration under -fno-standalone-debug // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E" // CHECK-SAME: scope: [[TEST3:![0-9]+]] +// CHECK-NOT: DIFlagEnumClass // CHECK-SAME: elements: [[TEST_ENUMS]] // CHECK-SAME: identifier: "_ZTSN5test31EE" // CHECK: [[TEST3]] = !DINamespace(name: "test3" @@ -78,6 +80,7 @@ void func(E *) { namespace test4 { // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E" // CHECK-SAME: scope: [[TEST4:![0-9]+]] +// CHECK-NOT: DIFlagEnumClass // CHECK-SAME: elements: [[TEST_ENUMS]] // CHECK-SAME: identifier: "_ZTSN5test41EE" // CHECK: [[TEST4]] = !DINamespace(name: "test4" diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp index 1db62d96d5b6..40a6643e71f9 100644 --- a/test/CodeGenCXX/debug-info-function-context.cpp +++ b/test/CodeGenCXX/debug-info-function-context.cpp @@ -28,10 +28,10 @@ int global_namespace_variable = 1; // CHECK: ![[FILE:[0-9]+]] = !DIFile(filename: "{{.*}}context.cpp", // CHECK: ![[C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK: ![[NS:.*]] = !DINamespace(name: "ns" -// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true +// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: ![[C]],{{.*}} DISPFlagDefinition -// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true +// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: ![[C]],{{.*}} DISPFlagDefinition -// CHECK: !DISubprogram(name: "global_function",{{.*}} scope: ![[FILE]],{{.*}} isDefinition: true +// CHECK: !DISubprogram(name: "global_function",{{.*}} scope: ![[FILE]],{{.*}} DISPFlagDefinition -// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS]],{{.*}} isDefinition: true +// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS]],{{.*}} DISPFlagDefinition diff --git a/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/test/CodeGenCXX/debug-info-gline-tables-only.cpp index d98b27872d62..ceb7856addc6 100644 --- a/test/CodeGenCXX/debug-info-gline-tables-only.cpp +++ b/test/CodeGenCXX/debug-info-gline-tables-only.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -fno-rtti -debug-info-kind=line-tables-only -S -emit-llvm -o - | FileCheck %s -// Checks that clang with "-gline-tables-only" doesn't emit debug info +// RUN: %clang_cc1 %s -fno-rtti -debug-info-kind=line-directives-only -S -emit-llvm -o - | FileCheck %s +// Checks that clang with "-gline-tables-only" or "-gline-directives-only" doesn't emit debug info // for variables and types. // CHECK-NOT: DW_TAG_namespace diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp index 7b57c08a1097..0ede3c6e48b7 100644 --- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -16,12 +16,12 @@ void foo() { static A stat; } -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 12,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 12,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 16,{{.*}} isLocal: true, isDefinition: true -// CHECK-NOKEXT: !DISubprogram({{.*}} isLocal: true, isDefinition: true +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 12,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 12,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-KEXT: !DISubprogram({{.*}} isLocal: true, isDefinition: true +// CHECK-KEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition diff --git a/test/CodeGenCXX/debug-info-inlined.cpp b/test/CodeGenCXX/debug-info-inlined.cpp index 53e2cc9289c2..d36715bcfcb6 100644 --- a/test/CodeGenCXX/debug-info-inlined.cpp +++ b/test/CodeGenCXX/debug-info-inlined.cpp @@ -26,4 +26,4 @@ B::B() : Forward(WithDtor()) {} // CHECK-SAME: !dbg ![[INL:[0-9]+]] // CHECK: ![[INL]] = !DILocation(line: 10, scope: ![[SP:[0-9]+]], inlinedAt: -// CHECK: ![[SP]] = distinct !DISubprogram(name: "Base", {{.*}}isDefinition: true +// CHECK: ![[SP]] = distinct !DISubprogram(name: "Base", {{.*}} DISPFlagDefinition diff --git a/test/CodeGenCXX/debug-info-lambda.cpp b/test/CodeGenCXX/debug-info-lambda.cpp new file mode 100644 index 000000000000..a10765de3777 --- /dev/null +++ b/test/CodeGenCXX/debug-info-lambda.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm \ +// RUN: -debug-info-kind=line-tables-only -dwarf-column-info -std=c++11 %s -o - | FileCheck %s + +// CHECK-LABEL: define{{.*}}lambda_in_func +void lambda_in_func(int &ref) { + // CHECK: [[ref_slot:%.*]] = getelementptr inbounds %class.anon, %class.anon* {{.*}}, i32 0, i32 0, !dbg [[lambda_decl_loc:![0-9]+]] + // CHECK-NEXT: %1 = load i32*, i32** %ref.addr, align {{.*}}, !dbg [[capture_init_loc:![0-9]+]] + // CHECK-NEXT: store i32* %1, i32** %0, align {{.*}}, !dbg [[lambda_decl_loc]] + // CHECK-NEXT: call {{.*}}void {{.*}}, !dbg [[lambda_call_loc:![0-9]+]] + + auto helper = [ // CHECK: [[lambda_decl_loc]] = !DILocation(line: [[@LINE]], column: 17 + &]() { // CHECK: [[capture_init_loc]] = !DILocation(line: [[@LINE]], column: 18 + ++ref; + }; + helper(); // CHECK: [[lambda_call_loc]] = !DILocation(line: [[@LINE]] +} diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp index a1c4ef9eea25..100cfa6e5e9a 100644 --- a/test/CodeGenCXX/debug-info-line.cpp +++ b/test/CodeGenCXX/debug-info-line.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s // RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-directives-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-directives-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s int &src(); int *sink(); diff --git a/test/CodeGenCXX/debug-info-member.cpp b/test/CodeGenCXX/debug-info-member.cpp index 7ba97b5b54e7..68d02526131b 100644 --- a/test/CodeGenCXX/debug-info-member.cpp +++ b/test/CodeGenCXX/debug-info-member.cpp @@ -1,5 +1,5 @@ // FIXME: Check IR rather than asm, then triple is not needed. -// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public +// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public class A { public: int x; diff --git a/test/CodeGenCXX/debug-info-method-spec.cpp b/test/CodeGenCXX/debug-info-method-spec.cpp index c00da004f456..0c803fdf6bf5 100644 --- a/test/CodeGenCXX/debug-info-method-spec.cpp +++ b/test/CodeGenCXX/debug-info-method-spec.cpp @@ -1,5 +1,5 @@ // FIXME: Check IR rather than asm, then triple is not needed. -// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification +// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification // Radar 9254491 class A { public: diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp index e83d7e94230d..0ce13a02e319 100644 --- a/test/CodeGenCXX/debug-info-ms-abi.cpp +++ b/test/CodeGenCXX/debug-info-ms-abi.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -gcodeview-ghash -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,GHASH // Tests that certain miscellaneous features work in the MS ABI. @@ -29,19 +30,25 @@ Foo::Nested n; // CHECK: ![[vptr_ty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[vshape]], size: 32 // CHECK: ![[f]] = !DISubprogram(name: "f", -// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, +// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 0, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, +// CHECK-SAME: spFlags: DISPFlagVirtual // CHECK: ![[g]] = !DISubprogram(name: "g", -// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1, +// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 1, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, +// CHECK-SAME: spFlags: DISPFlagVirtual // CHECK: ![[h]] = !DISubprogram(name: "h", -// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, +// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 2, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, +// CHECK-SAME: spFlags: DISPFlagVirtual // CHECK: ![[i]] = !DISubprogram(name: "i", // CHECK-SAME: flags: DIFlagPrototyped | DIFlagStaticMember // CHECK-NEXT: ![[dummy:[0-9]+]] = !DISubroutineType(types: ![[Signature:[0-9]+]]) // CHECK: ![[Signature]] = !{null, ![[BasicInt:[0-9]+]], ![[BasicInt]]} // CHECK: ![[BasicInt]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + +// CHECK: !{{[0-9]+}} = !{i32 2, !"CodeView", i32 1} +// GHASH: !{{[0-9]+}} = !{i32 2, !"CodeViewGHash", i32 1} diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp index d6fdee62d677..88449c8d6b75 100644 --- a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp +++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple i686--windows -emit-llvm -debug-info-kind=line-tables-only -x c++ %s -fms-extensions -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686--windows -emit-llvm -debug-info-kind=line-directives-only -x c++ %s -fms-extensions -o - | FileCheck %s struct __declspec(dllexport) S { virtual ~S(); }; struct __declspec(dllexport) T { virtual ~T(); }; diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index 296c99efc8eb..be88feda1112 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -std=c++11 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-directives-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLI %s // RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s namespace A { @@ -89,7 +90,7 @@ void C::c() {} // CHECK: [[LEX2]] = distinct !DILexicalBlock(scope: [[LEX1:![0-9]+]], file: [[FOOCPP]], // CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC:![0-9]+]], file: [[FOOCPP]], -// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} isDefinition: true +// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition // CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT:![0-9]+]], // CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27) // CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", @@ -102,7 +103,7 @@ void C::c() {} // CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1:![0-9]+]] // CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagDefinition // CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]] // CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]] // CHECK: [[BAZ]] = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", scope: [[NS]], file: [[FOOCPP]], @@ -116,15 +117,19 @@ void C::c() {} // CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9 // CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]] // CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]] -// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} isDefinition: true +// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} DISPFlagDefinition // CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]] -// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} isDefinition: true +// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} DISPFlagDefinition // CHECK: ![[C]] = !DINamespace(name: "C", // CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit( // CHECK-GMLT-SAME: emissionKind: LineTablesOnly, // CHECK-GMLT-NOT: imports: +// CHECK-GMLI: [[CU:![0-9]+]] = distinct !DICompileUnit( +// CHECK-GMLI-SAME: emissionKind: DebugDirectivesOnly, +// CHECK-GMLI-NOT: imports: + // CHECK-NOLIMIT: !DICompositeType(tag: DW_TAG_structure_type, name: "bar",{{.*}} line: 6, // CHECK-NOLIMIT-NOT: DIFlagFwdDecl // CHECK-NOLIMIT-SAME: ){{$}} diff --git a/test/CodeGenCXX/debug-info-static-fns.cpp b/test/CodeGenCXX/debug-info-static-fns.cpp index 59c7471f7ca6..2c8ed8f26c56 100644 --- a/test/CodeGenCXX/debug-info-static-fns.cpp +++ b/test/CodeGenCXX/debug-info-static-fns.cpp @@ -10,4 +10,4 @@ namespace A { // CHECK: define internal i32 @_ZN1AL1aEi({{.*}} !dbg [[DBG:![0-9]+]] // CHECK: [[DBG]] = distinct !DISubprogram(name: "a", linkageName: "_ZN1AL1aEi", // CHECK-SAME: line: 4 -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagDefinition diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp index c8d8a1de855d..cd51b522505d 100644 --- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=limited %s -o - | FileCheck %s -// Run again with -gline-tables-only and verify we don't crash. We won't output +// Run again with -gline-tables-only or -gline-directives-only and verify we don't crash. We won't output // type info at all. // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=line-tables-only %s -o - | FileCheck %s -check-prefix LINES-ONLY +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=line-directives-only %s -o - | FileCheck %s -check-prefix LINES-ONLY // LINES-ONLY-NOT: !DICompositeType(tag: DW_TAG_structure_type diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index a6aa1a05a256..db6006cab820 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -22,6 +22,19 @@ inline int add3(int x) { // CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression()) // CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", // CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] +// +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "var" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateTypeParameter(name: "T", type: [[TY:![0-9]+]]) +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "var" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateTypeParameter(name: "P", type: {{![0-9]+}}) +// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( +// CHECK-SAME: name: "varray" +// CHECK-SAME: templateParams: {{![0-9]+}} +// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1) // CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" @@ -103,3 +116,15 @@ void f2() { // declaration/reference in the compile unit. // CHECK: !DISubprogram(name: "MyClass" // CHECK-SAME: scope: [[C]] + +template <typename T> +T var = T(); +template <typename P> +P var<P *> = P(); +template <typename T, int N> +T varray[N]; +void f3() { + var<int> = 1; + var<int *> = 1; + varray<int, 1>[0] = 1; +} diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp index 565992ad2a3d..3dbabafdd87d 100644 --- a/test/CodeGenCXX/debug-info-thunk-msabi.cpp +++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp @@ -12,8 +12,8 @@ class __declspec(dllexport) A { // // CHECK: ![[SP]] = distinct !DISubprogram( // CHECK-SAME: line: 4 -// CHECK-SAME: isDefinition: true // CHECK-SAME: DIFlagArtificial +// CHECK-SAME: DISPFlagDefinition // CHECK-SAME: ){{$}} // // CHECK: ![[DBG]] = !DILocation(line: 0 diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index 56dec93f6b39..f6130cc28ced 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -86,7 +86,7 @@ namespace Test4 { }; } void C::c() {} -// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A0x{{[^@]*}}@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk void C::f() {} // Force C::f to be used. @@ -268,9 +268,9 @@ namespace Test12 { // // ITANIUM: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N6Test121C1fEv" // ITANIUM-SAME: line: 261 - // ITANIUM-SAME: isDefinition: true // ITANIUM-SAME: DIFlagArtificial // ITANIUM-SAME: DIFlagThunk + // ITANIUM-SAME: DISPFlagDefinition // ITANIUM-SAME: ){{$}} // // ITANIUM: ![[DBG]] = !DILocation(line: 0 diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp index 6c35f301f968..73bdaf0abc53 100644 --- a/test/CodeGenCXX/debug-info-vla.cpp +++ b/test/CodeGenCXX/debug-info-vla.cpp @@ -13,7 +13,7 @@ int (*fp)(int[][*]) = nullptr; // CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]} // CHECK: [[NOCOUNT]] = !DISubrange(count: -1) // -// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr", {{.*}}flags: DIFlagArtificial +// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr0", {{.*}}flags: DIFlagArtificial // CHECK: !DICompositeType(tag: DW_TAG_array_type, // CHECK-NOT: size: // CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp index 0b3d7e17e3fa..beea56ce7368 100644 --- a/test/CodeGenCXX/debug-info-windows-dtor.cpp +++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s struct A { virtual ~A() {} diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 6d6d0c7d19cf..8ac4016493c5 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -103,7 +103,7 @@ Cls obj; // CHECK: [[FUNC:[0-9]+]] = distinct !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE" // CHECK-SAME: type: {{![0-9]+}} -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagDefinition // CHECK: [[PR14763:![0-9]+]] = !DINamespace(name: "pr14763" namespace pr14763 { diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp index 1717fc468656..324c0926fb9f 100644 --- a/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -40,7 +40,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // A: 10 -// CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}} DISPFlagDefinition // Back to A. -- 78 // CHECK: ![[LAM_A:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]], @@ -52,7 +52,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: DIFlagPublic // B: 14 -// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}} DISPFlagDefinition // Back to B. -- 67 // CHECK: ![[LAM_B:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]], @@ -68,7 +68,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: DIFlagPublic // C: 17 -// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}} DISPFlagDefinition // Back to C. -- 55 // CHECK: ![[LAM_C:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]], @@ -85,7 +85,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: DIFlagPublic // D: 18 -// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}} DISPFlagDefinition // Back to D. -- 24 // CHECK: ![[LAM_D:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]], diff --git a/test/CodeGenCXX/debug-prefix-map-lambda.cpp b/test/CodeGenCXX/debug-prefix-map-lambda.cpp new file mode 100644 index 000000000000..f0fb1a312c8b --- /dev/null +++ b/test/CodeGenCXX/debug-prefix-map-lambda.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: -fdebug-prefix-map=%S=/SOURCE_ROOT %s -emit-llvm -o - | FileCheck %s + +template <typename T> void b(T) {} +void c() { + // CHECK: !DISubprogram(name: "b<(lambda at + // CHECK-SAME: SOURCE_ROOT + // CHECK-SAME: [[@LINE+1]]:{{[0-9]+}})>" + b([]{}); +} diff --git a/test/CodeGenCXX/dllexport-missing-key.cpp b/test/CodeGenCXX/dllexport-missing-key.cpp new file mode 100644 index 000000000000..90e736f6fad3 --- /dev/null +++ b/test/CodeGenCXX/dllexport-missing-key.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix=GNU %s + +class __declspec(dllexport) QAbstractLayoutStyleInfo { +public: + QAbstractLayoutStyleInfo() : m_isWindow(false) {} + virtual ~QAbstractLayoutStyleInfo() {} + + virtual bool hasChangedCore() const { return false; } + + virtual void invalidate() {} + + virtual double windowMargin(bool orientation) const = 0; + + bool isWindow() const { return m_isWindow; } + +protected: + bool m_isWindow; +}; + +// GNU-DAG: @_ZTV24QAbstractLayoutStyleInfo = weak_odr dso_local dllexport +// GNU-DAG: @_ZTS24QAbstractLayoutStyleInfo = linkonce_odr +// GNU-DAG: @_ZTI24QAbstractLayoutStyleInfo = linkonce_odr diff --git a/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp b/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp new file mode 100644 index 000000000000..3866731a3cd9 --- /dev/null +++ b/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc \ +// RUN: -disable-llvm-passes \ +// RUN: -fno-dllexport-inlines -emit-llvm -O1 -o - | \ +// RUN: FileCheck --check-prefix=CHECK --check-prefix=NOEXPORTINLINE %s + +// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc \ +// RUN: -disable-llvm-passes \ +// RUN: -emit-llvm -O1 -o - | \ +// RUN: FileCheck --check-prefix=CHECK --check-prefix=EXPORTINLINE %s + + +struct __declspec(dllexport) ExportedClass { + + // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InclassDefFunc@ExportedClass@@ + // EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@ExportedClass@@ + void InclassDefFunc() {} + + // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ" + int InclassDefFuncWithStaticVariable() { + // CHECK-DAG: @"?static_variable@?1??InclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 + static int static_variable = 0; + ++static_variable; + return static_variable; + } + + // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFunctWithLambdaStaticVariable@ExportedClass@@QEAAHXZ" + int InclassDefFunctWithLambdaStaticVariable() { + // CHECK-DAG: @"?static_x@?2???R<lambda_1>@?0??InclassDefFunctWithLambdaStaticVariable@ExportedClass@@QEAAHXZ@QEBA?A?<auto>@@XZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 + return ([]() { static int static_x; return ++static_x; })(); + } + + // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InlineOutclassDefFunc@ExportedClass@@QEAAXXZ + // EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InlineOutclassDefFunc@ExportedClass@@QEAAXXZ + inline void InlineOutclassDefFunc(); + + // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InlineOutclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ" + inline int InlineOutclassDefFuncWithStaticVariable(); + + // CHECK-DAG: define dso_local dllexport void @"?OutoflineDefFunc@ExportedClass@@QEAAXXZ" + void OutoflineDefFunc(); +}; + +void ExportedClass::OutoflineDefFunc() {} + +inline void ExportedClass::InlineOutclassDefFunc() {} + +inline int ExportedClass::InlineOutclassDefFuncWithStaticVariable() { + static int static_variable = 0; + return ++static_variable; +} + +void ExportedClassUser() { + ExportedClass a; + a.InclassDefFunc(); + a.InlineOutclassDefFunc(); +} + +template<typename T> +struct __declspec(dllexport) TemplateExportedClass { + void InclassDefFunc() {} + + int InclassDefFuncWithStaticVariable() { + static int static_x = 0; + return ++static_x; + } +}; + +class A11{}; +class B22{}; + +// CHECK-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateExportedClass@VA11@@@@QEAAXXZ" +// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VA11@@@@QEAAHXZ" +// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VA11@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 +template class TemplateExportedClass<A11>; + +// NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InclassDefFunc@?$TemplateExportedClass@VB22@@@@QEAAXXZ" +// EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateExportedClass@VB22@@@@QEAAXXZ +// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VB22@@@@QEAAHXZ" +// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VB22@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 +TemplateExportedClass<B22> b22; + +void TemplateExportedClassUser() { + b22.InclassDefFunc(); + b22.InclassDefFuncWithStaticVariable(); +} + + +template<typename T> +struct TemplateNoAttributeClass { + void InclassDefFunc() {} + int InclassDefFuncWithStaticLocal() { + static int static_x; + return ++static_x; + } +}; + +// CHECK-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateNoAttributeClass@VA11@@@@QEAAXXZ" +// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VA11 +// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VA11@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 +template class __declspec(dllexport) TemplateNoAttributeClass<A11>; + +// CHECK-DAG: define available_externally dllimport void @"?InclassDefFunc@?$TemplateNoAttributeClass@VB22@@@@QEAAXXZ" +// CHECK-DAG: define available_externally dllimport i32 @"?InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VB22@@@@QEAAHXZ" +// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VB22@@@@QEAAHXZ@4HA" = available_externally dllimport global i32 0, align 4 +extern template class __declspec(dllimport) TemplateNoAttributeClass<B22>; + +void TemplateNoAttributeClassUser() { + TemplateNoAttributeClass<B22> b22; + b22.InclassDefFunc(); + b22.InclassDefFuncWithStaticLocal(); +} + +struct __declspec(dllimport) ImportedClass { + // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InClassDefFunc@ImportedClass@@QEAAXXZ" + // EXPORTINLINE-DAG: define available_externally dllimport void @"?InClassDefFunc@ImportedClass@@QEAAXXZ" + void InClassDefFunc() {} + + // EXPORTINLINE-DAG: define available_externally dllimport i32 @"?InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ" + // NOEXPORTINLINE-DAG: define linkonce_odr dso_local i32 @"?InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ" + int InClassDefFuncWithStaticVariable() { + // CHECK-DAG: @"?static_variable@?1??InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ@4HA" = available_externally dllimport global i32 0, align 4 + static int static_variable = 0; + ++static_variable; + return static_variable; + } +}; + +int InClassDefFuncUser() { + // This is necessary for declare statement of ImportedClass::InClassDefFunc(). + ImportedClass c; + c.InClassDefFunc(); + return c.InClassDefFuncWithStaticVariable(); +} diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index a7b6aad357e5..16cfb8465845 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -43,7 +43,7 @@ __declspec(dllexport) extern int ExternGlobalDecl; // M64-DAG: @__ImageBase = external dso_local constant i8 -// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global +// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external global // dllexport implies a definition. // MSC-DAG: @"?GlobalDef@@3HA" = dso_local dllexport global i32 0, align 4 @@ -137,7 +137,7 @@ class __declspec(dllexport) i : h<> {}; // Declarations are not exported. // MSC-DAG: @"??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dso_local global -// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dso_local global +// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external global template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef; USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>) @@ -797,7 +797,7 @@ struct __declspec(dllexport) PR23308 { }; void PR23308::f(InternalLinkageType*) {} long use(PR23308* p) { p->f(nullptr); } -// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z" +// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A0x{{[^@]*}}@@@Z" template <typename T> struct PR23770BaseTemplate { void f() {} }; template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {}; @@ -1012,6 +1012,18 @@ struct __declspec(dllexport) LayerTreeImpl { // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QAE@XZ" // M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QEAA@XZ" +namespace pr39496 { +// Make sure dll attribute are inherited by static locals also in template +// specializations. +template <typename> struct __declspec(dllexport) S { int foo() { static int x; return x++; } }; +int foo() { S<int> s; return s.foo(); } +// MSC-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 + +template <typename> struct T { int foo() { static int x; return x++; } }; +template struct __declspec(dllexport) T<int>; +// MSC-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4 +} + class __declspec(dllexport) ACE_Shared_Object { public: virtual ~ACE_Shared_Object(); diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp index 7a7519f66831..f8034cfb47c1 100644 --- a/test/CodeGenCXX/dllimport-members.cpp +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -854,7 +854,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>) // Not importing specialization of a member variable template without explicit // dllimport. // MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external dso_local constant i32 -// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external dso_local constant i32 +// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external constant i32 template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>; USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>) diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 74f58cc3b171..e9f0e4795f79 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -78,7 +78,7 @@ USEVAR(GlobalRedecl2c) // NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC // and drop the dllimport with a warning. // MSC-DAG: @"?GlobalRedecl3@@3HA" = external dso_local global i32 -// GNU-DAG: @GlobalRedecl3 = external dso_local global i32 +// GNU-DAG: @GlobalRedecl3 = external global i32 __declspec(dllimport) extern int GlobalRedecl3; extern int GlobalRedecl3; // dllimport ignored USEVAR(GlobalRedecl3) @@ -137,7 +137,7 @@ template<typename T> __declspec(dllimport) int VarTmplRedecl2; USEVAR(VarTmplRedecl2<ImplicitInst_Imported>) // MSC-DAG: @"??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external dso_local global i32 -// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external dso_local global i32 +// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external global i32 template<typename T> __declspec(dllimport) extern int VarTmplRedecl3; template<typename T> extern int VarTmplRedecl3; // dllimport ignored USEVAR(VarTmplRedecl3<ImplicitInst_Imported>) @@ -996,3 +996,26 @@ template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func) // M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ" // G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv + +namespace pr39496 { +// Make sure dll attribute are inherited by static locals also in template +// specializations. +template <typename> struct __declspec(dllimport) S { int foo() { static int x; return x++; } }; +int foo() { S<int> s; return s.foo(); } +// MO1-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4 + +template <typename> struct T { int foo() { static int x; return x++; } }; +extern template struct __declspec(dllimport) T<int>; +int bar() { T<int> t; return t.foo(); } +// MO1-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4 + +template <typename T> struct __declspec(dllimport) U { + void foo() { + // Don't inherit dllimport to src before attaching the initializer. + static constexpr char src[] = {"hello"}; + T arr[sizeof(src)]; + } +}; +void baz() { U<int> u; u.foo(); } // No diagnostic. + +} diff --git a/test/CodeGenCXX/dso-local-executable.cpp b/test/CodeGenCXX/dso-local-executable.cpp index cc8d50f09c9e..ceb649e074a3 100644 --- a/test/CodeGenCXX/dso-local-executable.cpp +++ b/test/CodeGenCXX/dso-local-executable.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -O1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s // RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -fno-plt -O1 -emit-llvm %s -o - | FileCheck --check-prefix=NOPLT %s +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -O1 -emit-llvm %s -o - | FileCheck --check-prefix=MINGW %s // STATIC-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant // STATIC-DAG: @_ZTS1C = linkonce_odr dso_local constant @@ -19,6 +20,15 @@ // NOPLT-DAG: define dso_local void @_ZN1CC1Ev( // NOPLT-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv( +// MINGW-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant +// MINGW-DAG: @_ZTS1C = linkonce_odr dso_local constant +// MINGW-DAG: @_ZTI1C = linkonce_odr dso_local constant +// MINGW-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global +// MINGW-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global +// MINGW-DAG: define dso_local void @_ZN1CC2Ev( +// MINGW-DAG: define dso_local void @_ZN1CC1Ev( +// MINGW-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv( + struct C { C(); virtual void foo() {} @@ -48,15 +58,23 @@ int h() { } // namespace guard +// STATIC-DAG: @_ZN5test23barIiE1xE = available_externally dso_local constant i32 // STATIC-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev( +// NOPLT-DAG: @_ZN5test23barIiE1xE = available_externally dso_local constant i32 // NOPLT-DAG: define available_externally void @_ZN5test23barIcEC1Ev( +// MINGW-DAG: @_ZN5test23barIiE1xE = available_externally constant i32 +// MINGW-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev( namespace test2 { void foo(); template <typename T> struct bar { virtual void zed(); + static const int x = 42; bar() { foo(); } }; extern template class bar<char>; bar<char> abc; +const int *getX() { + return &bar<int>::x; +} } // namespace test2 diff --git a/test/CodeGenCXX/empty-struct-init-list.cpp b/test/CodeGenCXX/empty-struct-init-list.cpp new file mode 100644 index 000000000000..33f52ba7032d --- /dev/null +++ b/test/CodeGenCXX/empty-struct-init-list.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++14 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -emit-llvm -o - %s | FileCheck %s + +// CHECK: struct.a +typedef struct { } a; +typedef struct { + a b[]; +} c; + +// CHECK: {{(dso_local )?}}global %struct.c{{.*}}zeroinitializer +c d{ }; diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp index 0e9766220828..79fba7537146 100644 --- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp +++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp @@ -21,7 +21,7 @@ extern "C" void test_freefunc(int p1) { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer) // CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0) // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32* // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1) @@ -51,7 +51,7 @@ void S::test_method() { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer) // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] @@ -76,7 +76,7 @@ void test_lambda() { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer) // CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32* // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]] diff --git a/test/CodeGenCXX/float128-declarations.cpp b/test/CodeGenCXX/float128-declarations.cpp index 07e73b281728..18a25d9faba8 100644 --- a/test/CodeGenCXX/float128-declarations.cpp +++ b/test/CodeGenCXX/float128-declarations.cpp @@ -6,8 +6,6 @@ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -std=c++11 \ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 -// RUN: %clang_cc1 -emit-llvm -triple systemz-unknown-linux-gnu -std=c++11 \ -// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-SYSZ // RUN: %clang_cc1 -emit-llvm -triple i686-pc-openbsd -std=c++11 \ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // RUN: %clang_cc1 -emit-llvm -triple amd64-pc-openbsd -std=c++11 \ @@ -16,10 +14,13 @@ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // RUN: %clang_cc1 -emit-llvm -triple x86_64-pc-solaris2.11 -std=c++11 \ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %clang_cc1 -emit-llvm -triple i586-pc-haiku -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-haiku -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // /* Various contexts where type __float128 can appear. The different check - prefixes are due to different mangling on X86 and different calling - convention on SystemZ. */ + prefixes are due to different mangling on X86. */ /* Namespace */ namespace { @@ -92,7 +93,7 @@ int main(void) { // CHECK-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128 %arg) // CHECK-DAG: define linkonce_odr fp128 @_ZN2C16func2cEU10__float128(fp128 %arg) // CHECK-DAG: define linkonce_odr fp128 @_Z6func1tIU10__float128ET_S0_(fp128 %arg) -// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } // CHECK-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 // CHECK-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 // CHECK-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 @@ -114,7 +115,7 @@ int main(void) { // CHECK-X86-DAG: define linkonce_odr void @_ZN2C1C2Eg(%class.C1* %this, fp128 %arg) // CHECK-X86-DAG: define linkonce_odr fp128 @_ZN2C16func2cEg(fp128 %arg) // CHECK-X86-DAG: define linkonce_odr fp128 @_Z6func1tIgET_S0_(fp128 %arg) -// CHECK-X86-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-X86-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } // CHECK-X86-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 // CHECK-X86-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 // CHECK-X86-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 @@ -122,25 +123,3 @@ int main(void) { // CHECK-X86-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l // CHECK-X86-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 // CHECK-X86-DAG: store fp128 [[INC]], fp128* %f4l - -// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 -// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 -// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] -// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] -// CHECK-SYSZ-DAG: define internal void @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128* -// CHECK-SYSZ-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 -// CHECK-SYSZ-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 -// CHECK-SYSZ-DAG: @arr1f = global [10 x fp128] -// CHECK-SYSZ-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] -// CHECK-SYSZ-DAG: declare void @_Z6func1fU10__float128(fp128* -// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128* -// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C16func2cEU10__float128(fp128* -// CHECK-SYSZ-DAG: define linkonce_odr void @_Z6func1tIU10__float128ET_S0_(fp128* -// CHECK-SYSZ-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } -// CHECK-SYSZ-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 -// CHECK-SYSZ-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 -// CHECK-SYSZ-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 -// CHECK-SYSZ-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 -// CHECK-SYSZ-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l -// CHECK-SYSZ-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 -// CHECK-SYSZ-DAG: store fp128 [[INC]], fp128* %f4l diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp index e82c05ec8c81..7e1c1e8db93c 100644 --- a/test/CodeGenCXX/float16-declarations.cpp +++ b/test/CodeGenCXX/float16-declarations.cpp @@ -106,9 +106,9 @@ int main(void) { // CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}}) S1<_Float16> s1 = { 132.f16 }; -// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2 +// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2 // CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8* -// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i1 false) +// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @__const.main.s1 to i8*), i64 2, i1 false) _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + func1t(f1l) + s1.mem2 - f1n + f2n; @@ -123,7 +123,7 @@ int main(void) { // CHECK-DAG: store half [[INC]], half* %{{.*}}, align 2 _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; -// CHECK-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2 +// CHECK-DAG: @__const.main.arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2 float cvtf = f2n; //CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp index 203eb2142667..e9715a651f40 100644 --- a/test/CodeGenCXX/globalinit-loc.cpp +++ b/test/CodeGenCXX/globalinit-loc.cpp @@ -8,8 +8,8 @@ // CHECK: !dbg ![[DBG:.*]] // CHECK: !DISubprogram(linkageName: "_GLOBAL__sub_I_globalinit_loc.cpp" // CHECK-NOT: line: -// CHECK-SAME: isLocal: true -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagLocalToUnit +// CHECK-SAME: DISPFlagDefinition // CHECK: ![[DBG]] = !DILocation(line: 0, # 99 "someheader.h" class A { diff --git a/test/CodeGenCXX/inalloca-lambda.cpp b/test/CodeGenCXX/inalloca-lambda.cpp new file mode 100644 index 000000000000..ac85ee175268 --- /dev/null +++ b/test/CodeGenCXX/inalloca-lambda.cpp @@ -0,0 +1,11 @@ +// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s + +// PR28299 +// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet + +class A { + A(const A &); +}; +typedef void (*fptr_t)(A); +fptr_t fn1() { return [](A) {}; } + diff --git a/test/CodeGenCXX/inheriting-constructor-cleanup.cpp b/test/CodeGenCXX/inheriting-constructor-cleanup.cpp new file mode 100644 index 000000000000..3aac9ac9f78e --- /dev/null +++ b/test/CodeGenCXX/inheriting-constructor-cleanup.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s --check-prefix=EXCEPTIONS + +// PR36748 +// rdar://problem/45805151 + +// Classes to verify order of destroying function parameters. +struct S1 { + ~S1(); +}; +struct S2 { + ~S2(); +}; + +struct Base { + // Use variadic args to cause inlining the inherited constructor. + Base(const S1&, const S2&, const char *fmt, ...) {} +}; + +struct NonTrivialDtor { + ~NonTrivialDtor() {} +}; +struct Inheritor : public NonTrivialDtor, public Base { + using Base::Base; +}; + +void f() { + Inheritor(S1(), S2(), "foo"); + // CHECK-LABEL: define void @_Z1fv + // CHECK: %[[TMP1:.*]] = alloca %struct.S1 + // CHECK: %[[TMP2:.*]] = alloca %struct.S2 + // CHECK: call void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}}) + // CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) + // CHECK-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // CHECK-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) + + // EXCEPTIONS-LABEL: define void @_Z1fv + // EXCEPTIONS: %[[TMP1:.*]] = alloca %struct.S1 + // EXCEPTIONS: %[[TMP2:.*]] = alloca %struct.S2 + // EXCEPTIONS: invoke void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}}) + // EXCEPTIONS-NEXT: to label %[[CONT:.*]] unwind label %[[LPAD:.*]] + + // EXCEPTIONS: [[CONT]]: + // EXCEPTIONS-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) + // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) + + // EXCEPTIONS: [[LPAD]]: + // EXCEPTIONS: call void @_ZN14NonTrivialDtorD2Ev(%struct.NonTrivialDtor* {{.*}}) + // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) +} diff --git a/test/CodeGenCXX/inline-template-hint.cpp b/test/CodeGenCXX/inline-template-hint.cpp new file mode 100644 index 000000000000..3e64b1f74932 --- /dev/null +++ b/test/CodeGenCXX/inline-template-hint.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \ +// RUN: -finline-functions -emit-llvm -disable-llvm-passes -o - \ +// RUN: | FileCheck -allow-deprecated-dag-overlap %s \ +// RUN: --check-prefix=CHECK --check-prefix=SUITABLE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \ +// RUN: -finline-hint-functions -emit-llvm -disable-llvm-passes -o - \ +// RUN: | FileCheck -allow-deprecated-dag-overlap %s \ +// RUN: --check-prefix=CHECK --check-prefix=HINTED +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \ +// RUN: -fno-inline -emit-llvm -disable-llvm-passes -o - \ +// RUN: | FileCheck -allow-deprecated-dag-overlap %s \ +// RUN: --check-prefix=CHECK --check-prefix=NOINLINE + +struct A { + inline void int_run(int); + + template <class T> + inline void template_run(T); +}; + +// CHECK: @_ZN1A7int_runEi({{.*}}) [[ATTR:#[0-9]+]] +void A::int_run(int) {} +// CHECK: @_ZN1A12template_runIiEEvT_({{.*}}) [[ATTR]] +template <typename T> +void A::template_run(T) {} + +void bar() { + A().int_run(1); + A().template_run(1); +} + +// SUITABLE: attributes [[ATTR]] = { {{.*}}inlinehint{{.*}} } +// HINTED: attributes [[ATTR]] = { {{.*}}inlinehint{{.*}} } +// NOINLINE: attributes [[ATTR]] = { {{.*}}noinline{{.*}} } diff --git a/test/CodeGenCXX/lifetime-asan.cpp b/test/CodeGenCXX/lifetime-asan.cpp new file mode 100644 index 000000000000..9ccb28c876a1 --- /dev/null +++ b/test/CodeGenCXX/lifetime-asan.cpp @@ -0,0 +1,42 @@ +// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 %s | FileCheck %s -check-prefixes=CHECK,CHECK-O0 --implicit-check-not=llvm.lifetime +// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 \ +// RUN: -fsanitize=address -fsanitize-address-use-after-scope %s | \ +// RUN: FileCheck %s -check-prefixes=CHECK,CHECK-ASAN-USE-AFTER-SCOPE + +extern int bar(char *A, int n); + +struct X { X(); ~X(); int *p; }; +struct Y { Y(); int *p; }; + +extern "C" void a(), b(), c(), d(); + +// CHECK-LABEL: @_Z3foo +void foo(int n) { + // CHECK: call void @a() + a(); + + // CHECK: call void @b() + // CHECK-ASAN-USE-AFTER-SCOPE: store i1 false + // CHECK-ASAN-USE-AFTER-SCOPE: store i1 false + // CHECK: br i1 + // + // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start + // CHECK-ASAN-USE-AFTER-SCOPE: store i1 true + // CHECK: call void @_ZN1XC + // CHECK: br label + // + // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start + // CHECK-ASAN-USE-AFTER-SCOPE: store i1 true + // CHECK: call void @_ZN1YC + // CHECK: br label + // + // CHECK: call void @c() + // CHECK-ASAN-USE-AFTER-SCOPE: br i1 + // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end + // CHECK-ASAN-USE-AFTER-SCOPE: br i1 + // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end + b(), (n ? X().p : Y().p), c(); + + // CHECK: call void @d() + d(); +} diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp index f4cf53b0c5f5..3b93d70bd705 100644 --- a/test/CodeGenCXX/linetable-fnbegin.cpp +++ b/test/CodeGenCXX/linetable-fnbegin.cpp @@ -7,7 +7,7 @@ // CHECK: [[HPP:.*]] = !DIFile(filename: "./template.hpp", // CHECK: [[SP:.*]] = distinct !DISubprogram(name: "bar", // CHECK-SAME: file: [[HPP]], line: 22 -// CHECK-SAME: isDefinition: true +// CHECK-SAME: DISPFlagDefinition // We shouldn't need a lexical block for this function. // CHECK: [[DBG]] = !DILocation(line: 23, scope: [[SP]]) diff --git a/test/CodeGenCXX/linetable-virtual-variadic.cpp b/test/CodeGenCXX/linetable-virtual-variadic.cpp index cd746cdfdfe2..60dee5fe61b4 100644 --- a/test/CodeGenCXX/linetable-virtual-variadic.cpp +++ b/test/CodeGenCXX/linetable-virtual-variadic.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s // Crasher for PR22929. class Base { virtual void VariadicFunction(...); diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp index cd10384594ea..549ae54dfbe4 100644 --- a/test/CodeGenCXX/mangle-address-space.cpp +++ b/test/CodeGenCXX/mangle-address-space.cpp @@ -1,15 +1,64 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKNOOCL +// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINNOOCL +// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKOCL +// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINOCL -// CHECK-LABEL: define {{.*}}void @_Z2f0Pc +// CHECKNOOCL-LABEL: define {{.*}}void @_Z2f0Pc +// WINNOOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAD@Z" +// CHECKOCL-LABEL: define {{.*}}void @_Z2f0PU9CLgenericc +// WINOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_ASCLgeneric@$$CAD@__clang@@@Z" void f0(char *p) { } // CHECK-LABEL: define {{.*}}void @_Z2f0PU3AS1c +// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_AS@$00$$CAD@__clang@@@Z" void f0(char __attribute__((address_space(1))) *p) { } struct OpaqueType; typedef OpaqueType __attribute__((address_space(100))) * OpaqueTypePtr; // CHECK-LABEL: define {{.*}}void @_Z2f0PU5AS10010OpaqueType +// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_AS@$0GE@$$CAUOpaqueType@@@__clang@@@Z" void f0(OpaqueTypePtr) { } // CHECK-LABEL: define {{.*}}void @_Z2f1PU3AS1Kc -void f1(char __attribute__((address_space(1))) const *p) {}
\ No newline at end of file +// WIN-LABEL: define {{.*}}void @"?f1@@YAXPEAU?$_AS@$00$$CBD@__clang@@@Z" +void f1(char __attribute__((address_space(1))) const *p) {} + +// Ensure we can do return values, which change in MS mode. +// CHECK-LABEL: define {{.*}}float addrspace(1)* @_Z2f1PU3AS2Kc +// WIN-LABEL: define {{.*}}float addrspace(1)* @"?f1@@YAPEAU?$_AS@$00$$CAM@__clang@@PEAU?$_AS@$01$$CBD@2@@Z" +__attribute__((address_space(1))) float *f1(char __attribute__((address_space(2))) const *p) { return 0;} + +#if !defined(__OPENCL_CPP_VERSION__) +// Return value of address space without a pointer is invalid in opencl. +// Ensure we skip return values, since non-pointers aren't supposed to have an AS. +// CHECKNOOCL-LABEL: define {{.*}}float @_Z2f2PU3AS2Kc +// WINNOOCL-LABEL: define {{.*}}float @"?f2@@YA?AMQEAU?$_AS@$01$$CBD@__clang@@@Z" +__attribute__((address_space(1))) float f2(char __attribute__((address_space(2))) const * const p) { return 0;} +#endif + +#ifdef __OPENCL_CPP_VERSION__ +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU9CLprivatec +// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$_ASCLprivate@$$CAD@__clang@@@Z" +void ocl_f0(char __private *p) { } + +struct ocl_OpaqueType; +typedef ocl_OpaqueType __global * ocl_OpaqueTypePtr; + +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU8CLglobal14ocl_OpaqueType +// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$_ASCLglobal@$$CAUocl_OpaqueType@@@__clang@@@Z" +void ocl_f0(ocl_OpaqueTypePtr) { } + +// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f1PU10CLconstantKc +// WINOCL-LABEL: define {{.*}}void @"?ocl_f1@@YAXPEAU?$_ASCLconstant@$$CBD@__clang@@@Z" +void ocl_f1(char __constant const *p) {} + +// Ensure we can do return values, which change in MS mode. +// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f1PU9CLgenericKc +// WINOCL-LABEL: define {{.*}}float* @"?ocl_f1@@YAPEAU?$_ASCLconstant@$$CAM@__clang@@PEAU?$_ASCLgeneric@$$CBD@2@@Z" +__constant float *ocl_f1(char __generic const *p) { return 0;} + +// Ensure we skip return values, since non-pointers aren't supposed to have an AS. +// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f2PU9CLgenericKc +// WINOCL-LABEL: define {{.*}}float* @"?ocl_f2@@YAPEAU?$_ASCLgeneric@$$CAM@__clang@@QEAU?$_ASCLgeneric@$$CBD@2@@Z" +__generic float *ocl_f2(__generic char const * const p) { return 0;} +#endif diff --git a/test/CodeGenCXX/mangle-long-double.cpp b/test/CodeGenCXX/mangle-long-double.cpp index e248c474a2e7..177982b8f1aa 100644 --- a/test/CodeGenCXX/mangle-long-double.cpp +++ b/test/CodeGenCXX/mangle-long-double.cpp @@ -1,12 +1,8 @@ // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER64-LINUX // RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER-LINUX -// RUN: %clang_cc1 -triple powerpc64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER64-DARWIN -// RUN: %clang_cc1 -triple powerpc-apple-darwin9 %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER-DARWIN // RUN: %clang_cc1 -triple s390x-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=S390X-LINUX void f(long double) {} // POWER64-LINUX: _Z1fg // POWER-LINUX: _Z1fg -// POWER64-DARWIN: _Z1fe -// POWER-DARWIN: _Z1fe // S390X-LINUX: _Z1fg diff --git a/test/CodeGenCXX/mangle-ms-exception-spec.cpp b/test/CodeGenCXX/mangle-ms-exception-spec.cpp new file mode 100644 index 000000000000..1aaf2486ea14 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-exception-spec.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -Wno-noexcept-type -fms-compatibility-version=19.12 | FileCheck %s --check-prefix=CHECK --check-prefix=CXX11 +// RUN: %clang_cc1 -std=c++17 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=CHECK --check-prefix=NOCOMPAT +// RUN: %clang_cc1 -std=c++17 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-compatibility-version=19.12 | FileCheck %s --check-prefix=CHECK --check-prefix=CXX17 + +// Prove that mangling only changed for noexcept types under /std:C++17, not all noexcept functions +// CHECK-DAG: @"?nochange@@YAXXZ" +void nochange() noexcept {} + +// CXX11-DAG: @"?a@@YAXP6AHXZ@Z" +// NOCOMPAT-DAG: @"?a@@YAXP6AHXZ@Z" +// CXX17-DAG: @"?a@@YAXP6AHX_E@Z" +void a(int() noexcept) {} +// CHECK-DAG: @"?b@@YAXP6AHXZ@Z" +void b(int() noexcept(false)) {} +// CXX11-DAG: @"?c@@YAXP6AHXZ@Z" +// NOCOMPAT-DAG: @"?c@@YAXP6AHXZ@Z" +// CXX17-DAG: @"?c@@YAXP6AHX_E@Z" +void c(int() noexcept(true)) {} +// CHECK-DAG: @"?d@@YAXP6AHXZ@Z" +void d(int()) {} + +template <typename T> +class e; +template <typename T, typename... U> +class e<T(U...) noexcept> { + // CXX11-DAG: @"?ee@?$e@$$A6AXXZ@@EEAAXXZ" + // NOCOMPAT-DAG: @"?ee@?$e@$$A6AXXZ@@EEAAXXZ" + // CXX17-DAG: @"?ee@?$e@$$A6AXX_E@@EEAAXXZ" + virtual T ee(U &&...) noexcept {}; +}; + +e<void() noexcept> e1; + +template <typename T> +class f; +template <typename T, typename... U> +class f<T(U...)> { + // CHECK-DAG: @"?ff@?$f@$$A6AXXZ@@EEAAXXZ" + virtual T ff(U &&...) noexcept {}; +}; + +f<void()> f1; diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp index 8c6062b6d5ee..469a23afc8e1 100644 --- a/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s template<typename T> class Class { @@ -185,13 +187,35 @@ void spam() { // Unlike Itanium, there is no character code to indicate an argument pack. // Tested with MSVC 2013, the first version which supports variadic templates. -template <typename ...Ts> void variadic_fn_template(const Ts &...args) { } +template <typename ...Ts> void variadic_fn_template(const Ts &...args); +template <typename... Ts, typename... Us> +void multi_variadic_fn(Ts... ts, Us... us); +template <typename... Ts, typename C, typename... Us> +void multi_variadic_mixed(Ts... ts, C c, Us... us); void variadic_fn_instantiate() { variadic_fn_template(0, 1, 3, 4); variadic_fn_template(0, 1, 'a', "b"); + + // Directlly consecutive packs are separated by $$Z... + multi_variadic_fn<int, int>(1, 2, 3, 4, 5); + multi_variadic_fn<int, int, int>(1, 2, 3, 4, 5); + + // ...but not if another template parameter is between them. + multi_variadic_mixed<int, int>(1, 2, 3); + multi_variadic_mixed<int, int>(1, 2, 3, 4); } // CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z" +// X64: "??$variadic_fn_template@HHHH@@YAXAEBH000@Z" // CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z" +// X64: "??$variadic_fn_template@HHD$$BY01D@@YAXAEBH0AEBDAEAY01$$CBD@Z" +// CHECK: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z" +// X64: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z" +// CHECK: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z" +// X64: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z" +// CHECK: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z" +// X64: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z" +// CHECK: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z" +// X64: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z" template <typename ...Ts> struct VariadicClass { diff --git a/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp b/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp new file mode 100644 index 000000000000..47b1a38ffe18 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fno-rtti-data -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK + +namespace t1 { +struct A { +public: + virtual ~A(); + virtual A *f(); +}; +struct B { +public: + virtual ~B(); + +private: + virtual B *f(); +}; +struct C : A, B { + virtual ~C(); + +protected: + virtual C *f(); +}; +C c; +} +// Main external C::f impl: +// CHECK-DAG: "?f@C@t1@@MEAAPEAU12@XZ" +// New slot in C's vftable for B, returns C* directly: +// CHECK-DAG: "?f@C@t1@@O7EAAPEAU12@XZ" +// Return-adjusting thunk in C's vftable for B: +// CHECK-DAG: "?f@C@t1@@W7EAAPEAUB@2@XZ" diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp index f55713e6c0c8..c2461a30700f 100644 --- a/test/CodeGenCXX/mangle-ms-vector-types.cpp +++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp @@ -94,5 +94,9 @@ typedef __attribute__((ext_vector_type(4))) int vi4b; void foovi4b(vi4b) {} // CHECK: define dso_local void @"?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z" +typedef float __attribute__((__ext_vector_type__(3))) vf3; +void foovf3(vf3) {} +// CHECK: define dso_local void @"?foovf3@@YAXT?$__vector@M$02@__clang@@@Z" + // Clang does not support vectors of complex types, so we can't test the // mangling of them. diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 3cc1b1645e9c..e128c9443153 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -15,7 +15,7 @@ namespace N { namespace { int anonymous; -// CHECK-DAG: @"?anonymous@?A@N@@3HA" +// CHECK-DAG: @"?anonymous@?A0x{{[^@]*}}@N@@3HA" } } diff --git a/test/CodeGenCXX/mangle-win-ccs.cpp b/test/CodeGenCXX/mangle-win-ccs.cpp new file mode 100644 index 000000000000..f5ddf974cf8f --- /dev/null +++ b/test/CodeGenCXX/mangle-win-ccs.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-gnu -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-itanium -o - | FileCheck %s + +// GCC 5.1 began mangling these Windows calling conventions into function +// types, since they can be used for overloading. They've always been mangled +// in the MS ABI, but they are new to the Itanium mangler. Note that the main +// function definition does not use a calling convention. Only function types +// that appear later use it. + +template <typename Fn> static int func_as_ptr(Fn fn) { return int(fn); } + +void f_cdecl(int, int); +void __attribute__((stdcall)) f_stdcall(int, int); +void __attribute__((fastcall)) f_fastcall(int, int); +void __attribute__((thiscall)) f_thiscall(int, int); + +int as_cdecl() { return func_as_ptr(f_cdecl); } +int as_stdcall() { return func_as_ptr(f_stdcall); } +int as_fastcall() { return func_as_ptr(f_fastcall); } + +// CHECK: define dso_local i32 @_Z8as_cdeclv() +// CHECK: call i32 @_ZL11func_as_ptrIPFviiEEiT_(void (i32, i32)* @_Z7f_cdeclii) + +// CHECK: define dso_local i32 @_Z10as_stdcallv() +// CHECK: call i32 @_ZL11func_as_ptrIPU7stdcallFviiEEiT_(void (i32, i32)* @"\01__Z9f_stdcallii@8") + +// CHECK: define dso_local i32 @_Z11as_fastcallv() +// CHECK: call i32 @_ZL11func_as_ptrIPU8fastcallFviiEEiT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") + +// PR40107: We should mangle thiscall here but we don't because we can't +// disambiguate it from the member pointer case below where it shouldn't be +// mangled. +//int as_thiscall() { return func_as_ptr(f_thiscall); } +// CHECKX: define dso_local i32 @_Z11as_thiscallv() +// CHECKX: call i32 @_ZL11func_as_ptrIPU8thiscallFviiEEiT_(void (i32, i32)* @_Z10f_thiscallii) + +// CHECK: define dso_local void @_Z11funcRefTypeRU8fastcallFviiE(void (i32, i32)* %fr) +void funcRefType(void(__attribute__((fastcall)) & fr)(int, int)) { + fr(1, 2); +} + +struct Foo { void bar(int, int); }; + +// PR40107: In this case, the member function pointer uses the thiscall +// convention, but GCC doesn't mangle it, so we don't either. +// CHECK: define dso_local void @_Z15memptr_thiscallP3FooMS_FvvE(%struct.Foo* {{.*}}) +void memptr_thiscall(Foo *o, void (Foo::*mp)()) { (o->*mp)(); } + +// CHECK: define dso_local void @_Z12memptrCCTypeR3FooMS_U8fastcallFviiE(%struct.Foo* {{.*}}, { i32, i32 }* byval{{.*}}) +void memptrCCType(Foo &o, void (__attribute__((fastcall)) Foo::*mp)(int, int)) { + (o.*mp)(1, 2); +} + +// CHECK: define dso_local i32 @_Z17useTemplateFnTypev() +// CHECK: call i32 @_ZL14templateFnTypeIU8fastcallFviiEElPT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") +template <typename Fn> static long templateFnType(Fn *fn) { return long(fn); } +long useTemplateFnType() { return templateFnType(f_fastcall); } + +// CHECK: define weak_odr dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIsEvv@0"() +// CHECK: define dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIiEvv@0"() +template <typename T> void __attribute__((fastcall)) fnTemplate() {} +template void __attribute__((fastcall)) fnTemplate<short>(); +template <> void __attribute__((fastcall)) fnTemplate<int>() {} + +// CHECK: define weak_odr dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIsEPU8fastcallFviiEv@0"() +// CHECK: define dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIiEPU8fastcallFviiEv@0"() +typedef void (__attribute__((fastcall)) *fp_cc_t)(int, int); +template <typename T> fp_cc_t __attribute__((fastcall)) fnTempReturn() { return nullptr; } +template fp_cc_t __attribute__((fastcall)) fnTempReturn<short>(); +template <> fp_cc_t __attribute__((fastcall)) fnTempReturn<int>() { return nullptr; } diff --git a/test/CodeGenCXX/mangle-win64-ccs.cpp b/test/CodeGenCXX/mangle-win64-ccs.cpp new file mode 100644 index 000000000000..10c0430117c5 --- /dev/null +++ b/test/CodeGenCXX/mangle-win64-ccs.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-WIN +// RUN: %clang_cc1 -triple x86_64-linux-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-LIN + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +template <typename FTy> ptrdiff_t func_as_int(FTy *fp) { return ptrdiff_t(fp); } + +int f_plain(int); +int __attribute__((sysv_abi)) f_sysvabi(int); +int __attribute__((ms_abi)) f_msabi(int); +ptrdiff_t useThem() { + ptrdiff_t rv = 0; + rv += func_as_int(f_plain); + rv += func_as_int(f_sysvabi); + rv += func_as_int(f_msabi); + return rv; +} + +// CHECK-WIN: define dso_local i64 @_Z7useThemv() +// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_plaini) +// CHECK-WIN: call i64 @_Z11func_as_intIU8sysv_abiFiiEExPT_(i32 (i32)* @_Z9f_sysvabii) +// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_msabii) + +// CHECK-LIN: define i64 @_Z7useThemv() +// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z7f_plaini) +// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z9f_sysvabii) +// CHECK-LIN: call i64 @_Z11func_as_intIU6ms_abiFiiEElPT_(i32 (i32)* @_Z7f_msabii) diff --git a/test/CodeGenCXX/merge-functions.cpp b/test/CodeGenCXX/merge-functions.cpp index 2137f19c409c..20a286e02203 100644 --- a/test/CodeGenCXX/merge-functions.cpp +++ b/test/CodeGenCXX/merge-functions.cpp @@ -1,5 +1,5 @@ // REQUIRES: x86-registered-target -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O1 -fmerge-functions -emit-llvm -o - -x c++ < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O1 -fmerge-functions -emit-llvm -o - -x c++ < %s | FileCheck %s -implicit-check-not=_ZN1A1gEiPi // Basic functionality test. Function merging doesn't kick in on functions that // are too simple. @@ -9,6 +9,4 @@ struct A { virtual int g(int x, int *p) { return x ? *p : 1; } } a; -// CHECK: define {{.*}} @_ZN1A1gEiPi -// CHECK-NEXT: tail call i32 @_ZN1A1fEiPi -// CHECK-NEXT: ret +// CHECK: define {{.*}} @_ZN1A1fEiPi diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp index db9526633ff1..e6a0891cfc65 100644 --- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp +++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp @@ -3,8 +3,8 @@ // CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [ // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany1@@3US@@A", i32 0, i32 0) }, // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany2@@3US@@A", i32 0, i32 0) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?s@?$ExportedTemplate@H@@2US@@A@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) }, // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null } // CHECK: ] @@ -231,18 +231,18 @@ void force_usage() { DynamicDLLImportInitVSMangling::switch_test3(); } -// CHECK: define linkonce_odr dso_local void @"??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat +// CHECK: define linkonce_odr dso_local void @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ"() {{.*}} comdat // CHECK-NOT: and // CHECK-NOT: ?_Bfoo@ // CHECK: call x86_thiscallcc %class.A* @"??0A@@QAE@XZ" -// CHECK: call i32 @atexit(void ()* @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ") +// CHECK: call i32 @atexit(void ()* @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ") // CHECK: ret void // CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat // CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat -// CHECK: define internal void @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ" +// CHECK: define internal void @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ" // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"{{.*}}foo // CHECK: ret void diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 97b90ce6b9eb..b0d2b5654030 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -467,9 +467,9 @@ struct A { void *getA() { return (void*)new A(); } -// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A@@UAEPAXI@Z" +// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A0x{{[^@]*}}@@UAEPAXI@Z" // CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete) -// CHECK: define internal x86_thiscallcc void @"??1A@?A@@UAE@XZ" +// CHECK: define internal x86_thiscallcc void @"??1A@?A0x{{[^@]*}}@@UAE@XZ" // CHECK: (%"struct.(anonymous namespace)::A"* %this) // Check that we correctly transform __stdcall to __thiscall for ctors and diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp index cbbce2daaad8..f55b94acf1d7 100644 --- a/test/CodeGenCXX/microsoft-abi-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-throw.cpp @@ -22,7 +22,7 @@ // CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat // CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat // CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat -// CHECK-DAG: @"_TI1?AUFoo@?A@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A@@" to i8*) }, section ".xdata" +// CHECK-DAG: @"_TI1?AUFoo@?A0x{{[^@]*}}@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A0x{{[^@]*}}@@" to i8*) }, section ".xdata" struct N { ~N(); }; @@ -135,6 +135,6 @@ namespace { struct Foo { } foo_exc; } void *GetExceptionInfo_test2() { // CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ" -// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A@@" to i8*) +// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A0x{{[^@]*}}@@" to i8*) return __GetExceptionInfo(foo_exc); } diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp index c2f64f38417c..2b0231ffe74e 100644 --- a/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -160,5 +160,5 @@ struct E : D { E::E() {} E e; // Class with internal linkage has internal linkage thunks. -// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A@@QAEPAUB@@XZ" +// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A0x{{[^@]*}}@@QAEPAUB@@XZ" } diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp index 46e159c628f0..ae6602053b8c 100644 --- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp @@ -19,7 +19,7 @@ D d; // Force vbtable emission. // C: vbptr C // int c -// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20] +// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20], comdat, align 4 // CHECK-DAG: @"??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4] // CHECK-DAG: @"??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12] // CHECK-DAG: @"??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8] diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index 65370ab1ece5..f8d26f14f91d 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -36,10 +36,10 @@ struct W { virtual ~W() {} } w; } -// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] } -// RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1) +// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A0x{{[^@]*}}@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] } +// RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] } +// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] } struct X {}; template <class> struct Y : virtual X { diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp index ef8a5e486825..5ebe612e00ac 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp @@ -57,14 +57,14 @@ void f() { // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2 // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3 -// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AE" to i8*), i8** %ptr4 +// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AE" to i8*), i8** %ptr4 // CHECK32: } // // CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"() // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2 // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3 -// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AA" to i8*), i8** %ptr +// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AA" to i8*), i8** %ptr // CHECK64: } } @@ -125,7 +125,7 @@ void f() { // CHECK64: } // Thunk for calling the virtual function in internal class D. -// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...) +// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A0x{{[^@]*}}@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...) // CHECK32: #[[ATTR]] // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 // CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] @@ -133,7 +133,7 @@ void f() { // CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define internal void @"??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...) +// CHECK64-LABEL: define internal void @"??_9D@?A0x{{[^@]*}}@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...) // CHECK64: #[[ATTR]] // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 // CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] diff --git a/test/CodeGenCXX/msabi-swiftcall-cc.cpp b/test/CodeGenCXX/msabi-swiftcall-cc.cpp index d8205ed192a5..3cc90a83fbd1 100644 --- a/test/CodeGenCXX/msabi-swiftcall-cc.cpp +++ b/test/CodeGenCXX/msabi-swiftcall-cc.cpp @@ -12,8 +12,8 @@ void (__attribute__((__swiftcall__)) *p)(); namespace { void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { } } -// CHECK-DAG: @"?f@?A@@YSXXZ" -// CHECK-64-DAG: @"?f@?A@@YSXXZ" +// CHECK-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ" +// CHECK-64-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ" namespace n { void __attribute__((__swiftcall__)) f() {} @@ -44,8 +44,8 @@ void (__attribute__((__preserve_most__)) *q)(); namespace { void __attribute__((__preserve_most__)) __attribute__((__used__)) g() {} } -// CHECK-DAG: @"?g@?A@@YUXXZ" -// CHECK-64-DAG: @"?g@?A@@YUXXZ" +// CHECK-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ" +// CHECK-64-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ" namespace n { void __attribute__((__preserve_most__)) g() {} diff --git a/test/CodeGenCXX/no-lto-unit.cpp b/test/CodeGenCXX/no-lto-unit.cpp index 24b8fd01546a..3797f0742efb 100644 --- a/test/CodeGenCXX/no-lto-unit.cpp +++ b/test/CodeGenCXX/no-lto-unit.cpp @@ -2,6 +2,8 @@ // RUN: llvm-dis -o - %t | FileCheck %s // RUN: %clang_cc1 -flto=thin -flto-unit -fno-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s // RUN: llvm-dis -o - %t | FileCheck %s +// RUN: llvm-bcanalyzer -dump %t | FileCheck %s --check-prefix=NOLTOUNIT +// NOLTOUNIT: <FLAGS op0=0/> // CHECK-NOT: !type class A { diff --git a/test/CodeGenCXX/no_destroy.cpp b/test/CodeGenCXX/no_destroy.cpp new file mode 100644 index 000000000000..93e6ce17bb69 --- /dev/null +++ b/test/CodeGenCXX/no_destroy.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s + +struct NonTrivial { + ~NonTrivial(); +}; + +// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::no_destroy]] NonTrivial nt1; +// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::no_destroy]] thread_local NonTrivial nt2; + +struct NonTrivial2 { + ~NonTrivial2(); +}; + +// CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev +NonTrivial2 nt21; +// CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev +thread_local NonTrivial2 nt22; + +void f() { + // CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev + static NonTrivial2 nt21; + // CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev + thread_local NonTrivial2 nt22; +} + +// CHECK: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::always_destroy]] NonTrivial nt3; +// CHECK: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev +[[clang::always_destroy]] thread_local NonTrivial nt4; diff --git a/test/CodeGenCXX/noescape.cpp b/test/CodeGenCXX/noescape.cpp index 90d24de3da29..40bc839788ac 100644 --- a/test/CodeGenCXX/noescape.cpp +++ b/test/CodeGenCXX/noescape.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -fblocks -o - %s | FileCheck %s struct S { int a[4]; @@ -65,3 +65,32 @@ typedef void (*NoEscapeFunc)(__attribute__((noescape)) int *); void test3(NoEscapeFunc f, int *p) { f(p); } + +namespace TestByref { + +struct S { + S(); + ~S(); + S(const S &); + int a; +}; + +typedef void (^BlockTy)(void); +S &getS(); +void noescapefunc(__attribute__((noescape)) BlockTy); + +// Check that __block variables with reference types are handled correctly. + +// CHECK: define void @_ZN9TestByref4testEv( +// CHECK: %[[X:.*]] = alloca %[[STRUCT_TESTBYREF:.*]]*, align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: %[[V0:.*]] = load %[[STRUCT_TESTBYREF]]*, %[[STRUCT_TESTBYREF]]** %[[X]], align 8 +// CHECK: store %[[STRUCT_TESTBYREF]]* %[[V0]], %[[STRUCT_TESTBYREF]]** %[[BLOCK_CAPTURED]], align 8 + +void test() { + __block S &x = getS(); + noescapefunc(^{ (void)x; }); +} + +} diff --git a/test/CodeGenCXX/override-layout-packed-base.cpp b/test/CodeGenCXX/override-layout-packed-base.cpp index 26ed4b5d815a..03255f2f6ebf 100644 --- a/test/CodeGenCXX/override-layout-packed-base.cpp +++ b/test/CodeGenCXX/override-layout-packed-base.cpp @@ -1,26 +1,40 @@ -// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s +// RUN: %clang_cc1 -triple i686-windows-msvc -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s + +//#pragma pack(push, 1) // CHECK: Type: class B<0> +// CHECK: Size:40 // CHECK: FieldOffsets: [0, 32] // CHECK: Type: class B<1> +// CHECK: Size:40 // CHECK: FieldOffsets: [0, 32] -//#pragma pack(push, 1) template<int I> class B { int _b1; char _b2; }; -//#pragma pack(pop) // CHECK: Type: class C +// CHECK: Size:88 // CHECK: FieldOffsets: [80] class C : B<0>, B<1> { char _c; }; +// CHECK: Type: class D +// CHECK: Size:120 +// CHECK: FieldOffsets: [32] + +class D : virtual B<0>, virtual B<1> { + char _d; +}; + +//#pragma pack(pop) + void use_structs() { C cs[sizeof(C)]; + D ds[sizeof(D)]; } diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp index 8b33b854fd21..f0b15598c472 100644 --- a/test/CodeGenCXX/pragma-init_seg.cpp +++ b/test/CodeGenCXX/pragma-init_seg.cpp @@ -28,8 +28,8 @@ int z = f(); namespace internal_init { namespace { int x = f(); -// CHECK: @"?x@?A@internal_init@@3HA" = internal global i32 0, align 4 -// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A@internal_init@@YAXXZ", section ".asdf" +// CHECK: @"?x@?A0x{{[^@]*}}@internal_init@@3HA" = internal global i32 0, align 4 +// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A0x{{[^@]*}}@internal_init@@YAXXZ", section ".asdf" } } @@ -44,7 +44,7 @@ template <typename T> struct A { static const int x; }; template <typename T> const int A<T>::x = f(); template struct A<int>; // CHECK: @"?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr dso_local global i32 0, comdat, align 4 -// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB") +// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__E?x@?$A@H@explicit_template_instantiation@@2HB@@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB") } namespace implicit_template_instantiation { @@ -52,7 +52,7 @@ template <typename T> struct A { static const int x; }; template <typename T> const int A<T>::x = f(); int g() { return A<int>::x; } // CHECK: @"?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr dso_local global i32 0, comdat, align 4 -// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB") +// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__E?x@?$A@H@implicit_template_instantiation@@2HB@@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB") } // ... and here's where we emitted user level ctors. diff --git a/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp b/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp new file mode 100644 index 000000000000..da060f7902ef --- /dev/null +++ b/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +// Verify that the outer loop has the llvm.access.group property for the +// accesses outside and inside the inner loop, even when the inner loop +// is not perfectly nested. +void vectorize_imperfectly_nested_test(int *List, int Length) { +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) + for (int i = 0; i < Length; ++i) { + List[i * Length] = 42; +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) + for (int j = 1; j < Length - 1; ++j) + List[i * Length + j] = (i + j) * 2; + List[(i + 1) * Length - 1] = 21; + } +} + + +// CHECK: load i32, i32* %Length.addr, align 4, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]] + +// CHECK: %[[MUL:.+]] = mul nsw i32 %add, 2 +// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_3:[0-9]+]] +// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]] +// CHECK: store i32 21, i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_2]] +// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]] + +// CHECK: ![[ACCESS_GROUP_2]] = distinct !{} +// CHECK: ![[ACCESS_GROUP_LIST_3:[0-9]+]] = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]} +// CHECK: ![[ACCESS_GROUP_4]] = distinct !{} +// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_8:[0-9]+]]} +// CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]} +// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_10:[0-9]+]]} +// CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]} diff --git a/test/CodeGenCXX/pragma-loop-safety-nested.cpp b/test/CodeGenCXX/pragma-loop-safety-nested.cpp new file mode 100644 index 000000000000..deec06bbc827 --- /dev/null +++ b/test/CodeGenCXX/pragma-loop-safety-nested.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +// Verify that the outer loop has the llvm.access.group property for the +// accesses outside and inside the inner loop. +void vectorize_nested_test(int *List, int Length) { +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) + for (int i = 0; i < Length; ++i) { +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) + for (int j = 0; j < Length; ++j) + List[i * Length + j] = (i + j) * 2; + } +} + + +// CHECK: load i32, i32* %Length.addr, align 4, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]] +// CHECK: %[[MUL:.+]] = mul +// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_LIST_3:[0-9]+]] +// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]] +// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]] + +// CHECK: ![[ACCESS_GROUP_2]] = distinct !{} +// CHECK: ![[ACCESS_GROUP_LIST_3]] = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]} +// CHECK: ![[ACCESS_GROUP_4]] = distinct !{} +// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_8:[0-9]+]]} +// CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]} +// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_10:[0-9]+]]} +// CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]} diff --git a/test/CodeGenCXX/pragma-loop-safety-outer.cpp b/test/CodeGenCXX/pragma-loop-safety-outer.cpp new file mode 100644 index 000000000000..d99b86ffe23a --- /dev/null +++ b/test/CodeGenCXX/pragma-loop-safety-outer.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +// Verify that the outer loop has the inner loop's access in its +// llvm.loop.parallel_accesses property. +void vectorize_outer_test(int *List, int Length) { +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) + for (int i = 0; i < Length; i += 2) { +#pragma clang loop unroll(full) + for (int j = 0; j < 2; j += 1) + List[i + j] = (i + j) * 2; + } +} + +// CHECK: %[[MUL:.+]] = mul +// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]] +// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]] +// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]] + +// CHECK: ![[ACCESS_GROUP_2]] = distinct !{} +// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], +// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_9:[0-9]+]]} +// CHECK: ![[PARALLEL_ACCESSES_9]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]} diff --git a/test/CodeGenCXX/pragma-loop-safety.cpp b/test/CodeGenCXX/pragma-loop-safety.cpp index c6ce82737d0b..c0b10b0a6bd1 100644 --- a/test/CodeGenCXX/pragma-loop-safety.cpp +++ b/test/CodeGenCXX/pragma-loop-safety.cpp @@ -3,19 +3,19 @@ // Verify assume_safety vectorization is recognized. void vectorize_test(int *List, int Length) { // CHECK: define {{.*}} @_Z14vectorize_test -// CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID:[0-9]+]] -// CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] +// CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]] +// CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]] // CHECK-NEXT: [[CMP1:.+]] = icmp slt i32[[LOAD1_IV]],[[LOAD1_LEN]] // CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]] #pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]] // CHECK-DAG: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2 - // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.access.group ![[ACCESS_GROUP_2]] // CHECK-DAG: [[INDEX1:.+]] = sext i32[[SIV1]] to i64 - // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]] // CHECK-DAG: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]] - // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]] // CHECK-NEXT: br label [[LOOP1_INC:[^,]+]] List[i] = i * 2; @@ -26,19 +26,19 @@ void vectorize_test(int *List, int Length) { // Verify assume_safety interleaving is recognized. void interleave_test(int *List, int Length) { // CHECK: define {{.*}} @_Z15interleave_test -// CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID:[0-9]+]] -// CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] +// CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8:[0-9]+]] +// CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]] // CHECK-NEXT: [[CMP2:.+]] = icmp slt i32[[LOAD2_IV]],[[LOAD2_LEN]] // CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]] #pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]] // CHECK-DAG: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2 - // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.access.group ![[ACCESS_GROUP_8]] // CHECK-DAG: [[INDEX2:.+]] = sext i32[[SIV2]] to i64 - // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]] // CHECK-DAG: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]] - // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]] // CHECK-NEXT: br label [[LOOP2_INC:[^,]+]] List[i] = i * 2; @@ -46,9 +46,13 @@ void interleave_test(int *List, int Length) { } } -// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]]} +// CHECK: ![[ACCESS_GROUP_2]] = distinct !{} +// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]], ![[PARALLEL_ACCESSES_7:[0-9]+]]} // CHECK: ![[INTERLEAVE_1]] = !{!"llvm.loop.interleave.count", i32 1} // CHCCK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} -// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]]} +// CHECK: ![[PARALLEL_ACCESSES_7]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]} +// CHECK: ![[ACCESS_GROUP_8]] = distinct !{} +// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]], ![[PARALLEL_ACCESSES_11:[0-9]+]]} // CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} +// CHECK: ![[PARALLEL_ACCESSES_11]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_8]]} diff --git a/test/CodeGenCXX/pragma-pipeline.cpp b/test/CodeGenCXX/pragma-pipeline.cpp new file mode 100644 index 000000000000..6846f1544365 --- /dev/null +++ b/test/CodeGenCXX/pragma-pipeline.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple hexagon -std=c++11 -emit-llvm -o - %s | FileCheck %s + +void pipeline_disabled(int *List, int Length, int Value) { +// CHECK-LABEL: define {{.*}} @_Z17pipeline_disabled +#pragma clang loop pipeline(disable) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + List[i] = Value; + } +} + +void pipeline_not_disabled(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z21pipeline_not_disabled + for (int i = 0; i < Length; i++) { + List[i] = Value; + } +} + +void pipeline_initiation_interval(int *List, int Length, int Value) { +// CHECK-LABEL: define {{.*}} @_Z28pipeline_initiation_interval +#pragma clang loop pipeline_initiation_interval(10) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + List[i] = Value; + } +} + +void pipeline_disabled_on_nested_loop(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z32pipeline_disabled_on_nested_loop + for (int i = 0; i < Length; i++) { +#pragma clang loop pipeline(disable) + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + List[i * Length + j] = Value; + } + } +} + +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[PIPELINE_DISABLE:.*]]} +// CHECK: ![[PIPELINE_DISABLE]] = !{!"llvm.loop.pipeline.disable", i1 true} + +// CHECK-NOT:llvm.loop.pipeline + +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[PIPELINE_II_10:.*]]} +// CHECK: ![[PIPELINE_II_10]] = !{!"llvm.loop.pipeline.initiationinterval", i32 10} + +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[PIPELINE_DISABLE]]} diff --git a/test/CodeGenCXX/pragma-unroll-and-jam.cpp b/test/CodeGenCXX/pragma-unroll-and-jam.cpp new file mode 100644 index 000000000000..984212603450 --- /dev/null +++ b/test/CodeGenCXX/pragma-unroll-and-jam.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple arm-none-eabi -std=c++11 -emit-llvm -o - %s | FileCheck %s + +void unroll_and_jam(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z14unroll_and_jam +#pragma unroll_and_jam + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + List[i * Length + j] = Value; + } + } +} + +void unroll_and_jam_count(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z20unroll_and_jam_count +#pragma unroll_and_jam(4) + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_2:.*]] + List[i * Length + j] = Value; + } + } +} + +void nounroll_and_jam(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z16nounroll_and_jam +#pragma nounroll_and_jam + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + List[i * Length + j] = Value; + } + } +} + +void clang_unroll_plus_nounroll_and_jam(int *List, int Length, int Value) { + // CHECK-LABEL: define {{.*}} @_Z34clang_unroll_plus_nounroll_and_jam +#pragma nounroll_and_jam +#pragma unroll(4) + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + List[i * Length + j] = Value; + } + } +} + +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNJ_ENABLE:.*]]} +// CHECK: ![[UNJ_ENABLE]] = !{!"llvm.loop.unroll_and_jam.enable"} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNJ_4:.*]]} +// CHECK: ![[UNJ_4]] = !{!"llvm.loop.unroll_and_jam.count", i32 4} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNJ_DISABLE:.*]]} +// CHECK: ![[UNJ_DISABLE]] = !{!"llvm.loop.unroll_and_jam.disable"} +// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_4:.*]], ![[UNJ_DISABLE:.*]]} +// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4} diff --git a/test/CodeGenCXX/profile-remap.cpp b/test/CodeGenCXX/profile-remap.cpp new file mode 100644 index 000000000000..0fc7c7b40033 --- /dev/null +++ b/test/CodeGenCXX/profile-remap.cpp @@ -0,0 +1,29 @@ +// REQUIRES: x86-registered-target +// +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fprofile-sample-use=%S/Inputs/profile-remap.samples -fprofile-remapping-file=%S/Inputs/profile-remap.map -fexperimental-new-pass-manager -O2 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SAMPLES +// RUN: llvm-profdata merge -output %T.profdata %S/Inputs/profile-remap.proftext +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fprofile-instrument-use-path=%T.profdata -fprofile-remapping-file=%S/Inputs/profile-remap.map -fexperimental-new-pass-manager -O2 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-INSTR + +namespace Foo { + struct X {}; + bool cond(); + void bar(); + void baz(); + void function(X x) { + if (cond()) + bar(); + else + baz(); + } +} + +// CHECK: define {{.*}} @_ZN3Foo8functionENS_1XE() {{.*}} !prof [[FUNC_ENTRY:![0-9]*]] +// CHECK: br i1 {{.*}} !prof [[BR_WEIGHTS:![0-9]*]] +// +// FIXME: Laplace's rule of succession is applied to sample profiles... +// CHECK-SAMPLES-DAG: [[FUNC_ENTRY]] = !{!"function_entry_count", i64 1} +// CHECK-SAMPLES-DAG: [[BR_WEIGHTS]] = !{!"branch_weights", i32 11, i32 91} +// +// ... but not to instruction profiles. +// CHECK-INSTR-DAG: [[FUNC_ENTRY]] = !{!"function_entry_count", i64 100} +// CHECK-INSTR-DAG: [[BR_WEIGHTS]] = !{!"branch_weights", i32 10, i32 90} diff --git a/test/CodeGenCXX/speculative-vtt.cpp b/test/CodeGenCXX/speculative-vtt.cpp new file mode 100644 index 000000000000..120d95d4d482 --- /dev/null +++ b/test/CodeGenCXX/speculative-vtt.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -O2 -disable-llvm-passes -emit-llvm -o - | FileCheck %s +struct A { virtual ~A(); }; +template<typename T> struct B : virtual A { + ~B() override {} +}; +struct C : B<int>, B<float> { C(); ~C() override; }; +struct D : C { ~D() override; }; + +// We must not create a reference to B<int>::~B() here, because we're not going to emit it. +// CHECK-NOT: @_ZN1BIiED1Ev +// CHECK-NOT: @_ZTC1D0_1BIiE = +// CHECK-NOT: @_ZTT1D = available_externally +D *p = new D; diff --git a/test/CodeGenCXX/static-init-wasm.cpp b/test/CodeGenCXX/static-init-wasm.cpp index 68d139157e2d..579818ce5a20 100644 --- a/test/CodeGenCXX/static-init-wasm.cpp +++ b/test/CodeGenCXX/static-init-wasm.cpp @@ -38,7 +38,7 @@ void g() { // Test various aspects of static constructor calls. struct A { - A(); + A(); }; A theA; diff --git a/test/CodeGenCXX/thunk-returning-memptr.cpp b/test/CodeGenCXX/thunk-returning-memptr.cpp new file mode 100644 index 000000000000..0b7870c6d658 --- /dev/null +++ b/test/CodeGenCXX/thunk-returning-memptr.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple=i686 -emit-llvm -o - %s | FileCheck %s + + +struct X; +typedef void (X::*memptr)(); + +struct A { + virtual memptr f(); +}; + +struct B { + virtual memptr f(); +}; + +struct C : A, B { + C(); + memptr f() override __attribute__((noinline)) { return nullptr; }; +}; + +C::C() {} + +// Make sure the member pointer is returned from the thunk via the return slot. +// Because of the tail call, the return value cannot be copied into a local +// alloca. (PR39901) + +// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret %agg.result, %struct.C* %this) +// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret %agg.result diff --git a/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp b/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp new file mode 100644 index 000000000000..e7c9e9ac2a5a --- /dev/null +++ b/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO + +template<typename T> void used(T &) noexcept; + +extern "C" { + +// UNINIT-LABEL: test_attribute_uninitialized( +// UNINIT: alloca +// UNINIT-NEXT: call void +// ZERO-LABEL: test_attribute_uninitialized( +// ZERO: alloca +// ZERO-NEXT: call void +// PATTERN-LABEL: test_attribute_uninitialized( +// PATTERN: alloca +// PATTERN-NEXT: call void +void test_attribute_uninitialized() { + [[clang::uninitialized]] int i; + used(i); +} + +} // extern "C" diff --git a/test/CodeGenCXX/trivial-auto-var-init.cpp b/test/CodeGenCXX/trivial-auto-var-init.cpp new file mode 100644 index 000000000000..b795c0755bd4 --- /dev/null +++ b/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -0,0 +1,216 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO + +// None of the synthesized globals should contain `undef`. +// PATTERN-NOT: undef +// ZERO-NOT: undef + +template<typename T> void used(T &) noexcept; + +extern "C" { + +// UNINIT-LABEL: test_selfinit( +// ZERO-LABEL: test_selfinit( +// ZERO: store i32 0, i32* %self, align 4 +// PATTERN-LABEL: test_selfinit( +// PATTERN: store i32 -1431655766, i32* %self, align 4 +void test_selfinit() { + int self = self + 1; + used(self); +} + +// UNINIT-LABEL: test_block( +// ZERO-LABEL: test_block( +// ZERO: store i32 0, i32* %block +// PATTERN-LABEL: test_block( +// PATTERN: store i32 -1431655766, i32* %block +void test_block() { + __block int block; + used(block); +} + +// This type of code is currently not handled by zero / pattern initialization. +// The test will break when that is fixed. +// UNINIT-LABEL: test_goto_unreachable_value( +// ZERO-LABEL: test_goto_unreachable_value( +// ZERO-NOT: store {{.*}}%oops +// PATTERN-LABEL: test_goto_unreachable_value( +// PATTERN-NOT: store {{.*}}%oops +void test_goto_unreachable_value() { + goto jump; + int oops; + jump: + used(oops); +} + +// This type of code is currently not handled by zero / pattern initialization. +// The test will break when that is fixed. +// UNINIT-LABEL: test_goto( +// ZERO-LABEL: test_goto( +// ZERO: if.then: +// ZERO: br label %jump +// ZERO: store i32 0, i32* %oops, align 4 +// ZERO: br label %jump +// ZERO: jump: +// PATTERN-LABEL: test_goto( +// PATTERN: if.then: +// PATTERN: br label %jump +// PATTERN: store i32 -1431655766, i32* %oops, align 4 +// PATTERN: br label %jump +// PATTERN: jump: +void test_goto(int i) { + if (i) + goto jump; + int oops; + jump: + used(oops); +} + +// This type of code is currently not handled by zero / pattern initialization. +// The test will break when that is fixed. +// UNINIT-LABEL: test_switch( +// ZERO-LABEL: test_switch( +// ZERO: sw.bb: +// ZERO-NEXT: store i32 0, i32* %oops, align 4 +// ZERO: sw.bb1: +// ZERO-NEXT: call void @{{.*}}used +// PATTERN-LABEL: test_switch( +// PATTERN: sw.bb: +// PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4 +// PATTERN: sw.bb1: +// PATTERN-NEXT: call void @{{.*}}used +void test_switch(int i) { + switch (i) { + case 0: + int oops; + break; + case 1: + used(oops); + } +} + +// UNINIT-LABEL: test_vla( +// ZERO-LABEL: test_vla( +// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 +// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false) +// PATTERN-LABEL: test_vla( +// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 +// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop +// PATTERN: vla-setup.loop: +// PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 +// PATTERN: %vla.begin = bitcast i32* %vla to i8* +// PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]] +// PATTERN: br label %vla-init.loop +// PATTERN: vla-init.loop: +// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] +// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla +// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4 +// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end +// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop +// PATTERN: vla-init.cont: +// PATTERN: call void @{{.*}}used +void test_vla(int size) { + // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5. + // Neither can they be negative-sized. + // + // We don't use the former fact because some code creates zero-sized VLAs and + // doesn't use them. clang makes these share locations with other stack + // values, which leads to initialization of the wrong values. + // + // We rely on the later fact because it generates better code. + // + // Both cases are caught by UBSan. + int vla[size]; + int *ptr = vla; + used(ptr); +} + +// UNINIT-LABEL: test_struct_vla( +// ZERO-LABEL: test_struct_vla( +// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 +// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false) +// PATTERN-LABEL: test_struct_vla( +// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 +// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop +// PATTERN: vla-setup.loop: +// PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 +// PATTERN: %vla.begin = bitcast %struct.anon* %vla to i8* +// PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]] +// PATTERN: br label %vla-init.loop +// PATTERN: vla-init.loop: +// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] +// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla +// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16 +// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end +// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop +// PATTERN: vla-init.cont: +// PATTERN: call void @{{.*}}used +void test_struct_vla(int size) { + // Same as above, but with a struct that doesn't just memcpy. + struct { + float f; + char c; + void *ptr; + } vla[size]; + void *ptr = static_cast<void*>(vla); + used(ptr); +} + +// UNINIT-LABEL: test_zsa( +// ZERO-LABEL: test_zsa( +// ZERO: %zsa = alloca [0 x i32], align 4 +// ZERO-NOT: %zsa +// ZERO: call void @{{.*}}used +// PATTERN-LABEL: test_zsa( +// PATTERN: %zsa = alloca [0 x i32], align 4 +// PATTERN-NOT: %zsa +// PATTERN: call void @{{.*}}used +void test_zsa(int size) { + // Technically not valid, but as long as clang accepts them we should do + // something sensible (i.e. not store to the zero-size array). + int zsa[0]; + used(zsa); +} + +// UNINIT-LABEL: test_huge_uninit( +// ZERO-LABEL: test_huge_uninit( +// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, +// PATTERN-LABEL: test_huge_uninit( +// PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536, +void test_huge_uninit() { + // We can't emit this as an inline constant to a store instruction because + // SDNode hits an internal size limit. + char big[65536]; + used(big); +} + +// UNINIT-LABEL: test_huge_small_init( +// ZERO-LABEL: test_huge_small_init( +// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, +// ZERO: store i8 97, +// ZERO: store i8 98, +// ZERO: store i8 99, +// ZERO: store i8 100, +// PATTERN-LABEL: test_huge_small_init( +// PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536, +// PATTERN: store i8 97, +// PATTERN: store i8 98, +// PATTERN: store i8 99, +// PATTERN: store i8 100, +void test_huge_small_init() { + char big[65536] = { 'a', 'b', 'c', 'd' }; + used(big); +} + +// UNINIT-LABEL: test_huge_larger_init( +// ZERO-LABEL: test_huge_larger_init( +// ZERO: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536, +// PATTERN-LABEL: test_huge_larger_init( +// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536, +void test_huge_larger_init() { + char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + used(big); +} + +} // extern "C" diff --git a/test/CodeGenCXX/trivial_abi.cpp b/test/CodeGenCXX/trivial_abi.cpp index 2cf07b22581a..e37c8ff615a2 100644 --- a/test/CodeGenCXX/trivial_abi.cpp +++ b/test/CodeGenCXX/trivial_abi.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s // CHECK: %[[STRUCT_SMALL:.*]] = type { i32* } // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] } @@ -43,6 +43,13 @@ struct HasNonTrivial { NonTrivial m; }; +struct __attribute__((trivial_abi)) CopyMoveDeleted { + CopyMoveDeleted(int); + CopyMoveDeleted(const CopyMoveDeleted &) = delete; + CopyMoveDeleted(CopyMoveDeleted &&) = delete; + int a; +}; + // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 @@ -237,3 +244,11 @@ void calleeExceptionLarge(Large, Large); void testExceptionLarge() { calleeExceptionLarge(Large(), Large()); } + +// A class with deleted copy and move constructors can still be passed or +// returned in registers if the class is annotated with trivial_abi. + +// CHECK: define i64 @_Z19testCopyMoveDeletedi(i32 % +CopyMoveDeleted testCopyMoveDeleted(int a) { + return a; +} diff --git a/test/CodeGenCXX/type-metadata-thinlto.cpp b/test/CodeGenCXX/type-metadata-thinlto.cpp index 2a586fc4c37c..8bf39f129c40 100644 --- a/test/CodeGenCXX/type-metadata-thinlto.cpp +++ b/test/CodeGenCXX/type-metadata-thinlto.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s +// RUN: %clang_cc1 -flto=thin -flto-unit -fsplit-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s // RUN: llvm-modextract -o - -n 1 %t | llvm-dis | FileCheck %s +// RUN: llvm-modextract -b -o - -n 1 %t | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=LTOUNIT +// LTOUNIT: <FLAGS op0=8/> // CHECK: @_ZTV1A = linkonce_odr class A { diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp index 8e3e4bd182fe..a7a34673cdfc 100644 --- a/test/CodeGenCXX/type-metadata.cpp +++ b/test/CodeGenCXX/type-metadata.cpp @@ -82,8 +82,8 @@ // MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]] // MS: comdat($"??_7B@@6BA@@@"), !type [[A8]] // MS: comdat($"??_7C@@6B@"), !type [[A8]] -// MS: comdat($"??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]] -// MS: comdat($"??_7D@?A@@6BA@@@"), !type [[A8]] +// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]] +// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BA@@@"), !type [[A8]] // MS: comdat($"??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]] struct A { @@ -161,7 +161,7 @@ void af(A *a) { } // ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE -// MS: define internal void @"?df1@@YAXPEAUD@?A@@@Z" +// MS: define internal void @"?df1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z" void df1(D *d) { // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@") @@ -171,7 +171,7 @@ void df1(D *d) { } // ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE -// MS: define internal void @"?dg1@@YAXPEAUD@?A@@@Z" +// MS: define internal void @"?dg1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z" void dg1(D *d) { // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@") @@ -181,7 +181,7 @@ void dg1(D *d) { } // ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE -// MS: define internal void @"?dh1@@YAXPEAUD@?A@@@Z" +// MS: define internal void @"?dh1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z" void dh1(D *d) { // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]]) // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) @@ -191,7 +191,7 @@ void dh1(D *d) { } // ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE -// MS: define internal void @"?df2@@YAXPEAUD@?A@@@Z" +// MS: define internal void @"?df2@@YAXPEAUD@?A0x{{[^@]*}}@@@Z" __attribute__((no_sanitize("cfi"))) void df2(D *d) { // CFI-NVT-NOT: call i1 @llvm.type.test @@ -201,7 +201,7 @@ void df2(D *d) { } // ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE -// MS: define internal void @"?df3@@YAXPEAUD@?A@@@Z" +// MS: define internal void @"?df3@@YAXPEAUD@?A0x{{[^@]*}}@@@Z" __attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall"))) void df3(D *d) { // CFI-NVT-NOT: call i1 @llvm.type.test diff --git a/test/CodeGenCXX/ubsan-check-debuglocs.cpp b/test/CodeGenCXX/ubsan-check-debuglocs.cpp new file mode 100644 index 000000000000..96a697aca5eb --- /dev/null +++ b/test/CodeGenCXX/ubsan-check-debuglocs.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited \ +// RUN: -fsanitize=null %s -o - | FileCheck %s + +// Check that santizer check calls have a !dbg location. +// CHECK: define {{.*}}acquire{{.*}} !dbg +// CHECK-NOT: define +// CHECK: call void {{.*}}@__ubsan_handle_type_mismatch_v1 +// CHECK-SAME: !dbg + +struct SourceLocation { + SourceLocation acquire() {}; +}; +extern "C" void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc); +static void handleTypeMismatchImpl(SourceLocation *Loc) { Loc->acquire(); } +void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc) { + handleTypeMismatchImpl(Loc); +} diff --git a/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp b/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp new file mode 100644 index 000000000000..c0fa57d859c7 --- /dev/null +++ b/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck -check-prefixes=CHECK-NO-VIH %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility hidden -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-HIDDEN +// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility protected -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-PROTECTED + +// When a function is hidden due to -fvisibility-inlines-hidden option, static local variables of the function should not be hidden by the option. + +// CHECK-DAG: @_ZZ4funcvE3var = internal global i32 0 +// CHECK-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0 +// CHECK-DAG: @_ZZ12default_funcvE3var = internal global i32 0 +// CHECK-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat +// CHECK-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4 +// CHECK-DAG: define i32 @_Z4funcv() +// CHECK-DAG: define hidden i32 @_Z11hidden_funcv() +// CHECK-DAG: define i32 @_Z12default_funcv() +// CHECK-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv() +// CHECK-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv() +// CHECK-DAG: define linkonce_odr i32 @_Z19inline_default_funcv() +// CHECK-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}}) +// CHECK-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}}) + +// CHECK-NO-VIH-DAG: @_ZZ4funcvE3var = internal global i32 0 +// CHECK-NO-VIH-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0 +// CHECK-NO-VIH-DAG: @_ZZ12default_funcvE3var = internal global i32 0 +// CHECK-NO-VIH-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-NO-VIH-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat +// CHECK-NO-VIH-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-NO-VIH-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4 +// CHECK-NO-VIH-DAG: define i32 @_Z4funcv() +// CHECK-NO-VIH-DAG: define hidden i32 @_Z11hidden_funcv() +// CHECK-NO-VIH-DAG: define i32 @_Z12default_funcv() +// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z11inline_funcv() +// CHECK-NO-VIH-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv() +// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z19inline_default_funcv() +// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_ZN13ExportedClass10inl_methodEv({{.*}}) +// CHECK-NO-VIH-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}}) + +// CHECK-VIS-HIDDEN-DAG: @_ZZ4funcvE3var = internal global i32 0 +// CHECK-VIS-HIDDEN-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0 +// CHECK-VIS-HIDDEN-DAG: @_ZZ12default_funcvE3var = internal global i32 0 +// CHECK-VIS-HIDDEN-DAG: @_ZZ11inline_funcvE3var = linkonce_odr hidden global i32 0, comdat +// CHECK-VIS-HIDDEN-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat +// CHECK-VIS-HIDDEN-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-VIS-HIDDEN-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4 +// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z4funcv() +// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z11hidden_funcv() +// CHECK-VIS-HIDDEN-DAG: define i32 @_Z12default_funcv() +// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv() +// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv() +// CHECK-VIS-HIDDEN-DAG: define linkonce_odr i32 @_Z19inline_default_funcv() +// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}}) +// CHECK-VIS-HIDDEN-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}}) + +// CHECK-VIS-PROTECTED-DAG: @_ZZ4funcvE3var = internal global i32 0 +// CHECK-VIS-PROTECTED-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0 +// CHECK-VIS-PROTECTED-DAG: @_ZZ12default_funcvE3var = internal global i32 0 +// CHECK-VIS-PROTECTED-DAG: @_ZZ11inline_funcvE3var = linkonce_odr protected global i32 0, comdat +// CHECK-VIS-PROTECTED-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat +// CHECK-VIS-PROTECTED-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat +// CHECK-VIS-PROTECTED-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4 +// CHECK-VIS-PROTECTED-DAG: define protected i32 @_Z4funcv() +// CHECK-VIS-PROTECTED-DAG: define hidden i32 @_Z11hidden_funcv() +// CHECK-VIS-PROTECTED-DAG: define i32 @_Z12default_funcv() +// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv() +// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv() +// CHECK-VIS-PROTECTED-DAG: define linkonce_odr i32 @_Z19inline_default_funcv() +// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}}) +// CHECK-VIS-PROTECTED-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}}) + +int func(void) { + static int var = 0; + return var++; +} +inline int inline_func(void) { + static int var = 0; + return var++; +} +int __attribute__((visibility("hidden"))) hidden_func(void) { + static int var = 0; + return var++; +} +inline int __attribute__((visibility("hidden"))) inline_hidden_func(void) { + static int var = 0; + return var++; +} +int __attribute__((visibility("default"))) default_func(void) { + static int var = 0; + return var++; +} +inline int __attribute__((visibility("default"))) inline_default_func(void) { + static int var = 0; + return var++; +} +struct __attribute__((visibility("default"))) ExportedClass { + int inl_method() { + static int var = 0; + return var++; + } + int ext_method(); +}; +int ExportedClass::ext_method() { return inl_method(); } +void bar(void) { + func(); + inline_func(); + hidden_func(); + inline_hidden_func(); + default_func(); + inline_default_func(); +} diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp index 1b82cbc085c9..bd0494fe5dd5 100644 --- a/test/CodeGenCXX/vtable-align.cpp +++ b/test/CodeGenCXX/vtable-align.cpp @@ -10,5 +10,8 @@ struct A { void A::f() {} // CHECK-32: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 4 - +// CHECK-32: @_ZTS1A = constant [3 x i8] c"1A\00", align 1 +// CHECK-32: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 4 // CHECK-64: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 8 +// CHECK-64: @_ZTS1A = constant [3 x i8] c"1A\00", align 1 +// CHECK-64: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 8 diff --git a/test/CodeGenCXX/vtable-debug-info.cpp b/test/CodeGenCXX/vtable-debug-info.cpp index 8710c76e0bfa..0ac90b3ec1d3 100644 --- a/test/CodeGenCXX/vtable-debug-info.cpp +++ b/test/CodeGenCXX/vtable-debug-info.cpp @@ -1,6 +1,6 @@ // RUN: %clang -emit-llvm -S -g %s -o /dev/null // Radar 8730409 -// XFAIL: win32 +// XFAIL: windows-msvc // FIXME: This test crashes on *-pc-win32 // for lack of debugging support on -integrated-as (MCCOFF). diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 0c55eb26f7f1..d4f06ce6ce03 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -98,10 +98,10 @@ void use_F() { // C has no key function, so its vtable should have weak_odr linkage // and hidden visibility (rdar://problem/7523229). -// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}} +// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat, align 8{{$}} +// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}} // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. @@ -120,27 +120,27 @@ void use_F() { // defined in this translation unit, so its vtable should have // weak_odr linkage. // CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat, align 8{{$}} // F<short> is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage // CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat, align 8{{$}} // E<long> is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // linkonce_odr linkage. // CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // F<long> is an implicit template instantiation with no key function, // so its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // F<int> is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. @@ -171,8 +171,8 @@ void use_F() { // F<char> is an explicit specialization without a key function, so // its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant {{.*}}, comdat, -// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat, align 1{{$}} +// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat, align 8{{$}} // CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant {{.*}}, comdat, template <typename T> diff --git a/test/CodeGenCXX/wasm-args-returns.cpp b/test/CodeGenCXX/wasm-args-returns.cpp index 24adc8e08761..a7c4e1e282a1 100644 --- a/test/CodeGenCXX/wasm-args-returns.cpp +++ b/test/CodeGenCXX/wasm-args-returns.cpp @@ -3,16 +3,18 @@ // RUN: %clang_cc1 -O1 -triple wasm64-unknown-unknown -emit-llvm -o - %s \ // RUN: | FileCheck %s -#define concat_(x, y) x ## y +#define concat_(x, y) x##y #define concat(x, y) concat_(x, y) -#define test(T) \ +#define test(T) \ T forward(T x) { return x; } \ - void use(T x); \ - T concat(def_, T)(void); \ + void use(T x); \ + T concat(def_, T)(void); \ void concat(test_, T)(void) { use(concat(def_, T)()); } -struct one_field { double d; }; +struct one_field { + double d; +}; test(one_field); // CHECK: define double @_Z7forward9one_field(double returned %{{.*}}) // @@ -24,7 +26,9 @@ test(one_field); // CHECK: declare void @_Z3use9one_field(double) // CHECK: declare double @_Z13def_one_fieldv() -struct two_fields { double d, e; }; +struct two_fields { + double d, e; +}; test(two_fields); // CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret %{{.*}}, %struct.two_fields* byval nocapture readonly align 8 %{{.*}}) // @@ -38,8 +42,8 @@ test(two_fields); // CHECK: declare void @_Z14def_two_fieldsv(%struct.two_fields* sret) struct copy_ctor { - double d; - copy_ctor(copy_ctor const&); + double d; + copy_ctor(copy_ctor const &); }; test(copy_ctor); // CHECK: define void @_Z7forward9copy_ctor(%struct.copy_ctor* noalias sret %{{.*}}, %struct.copy_ctor* %{{.*}}) @@ -56,8 +60,8 @@ test(copy_ctor); // CHECK: declare void @_Z13def_copy_ctorv(%struct.copy_ctor* sret) struct __attribute__((aligned(16))) aligned_copy_ctor { - double d, e; - aligned_copy_ctor(aligned_copy_ctor const&); + double d, e; + aligned_copy_ctor(aligned_copy_ctor const &); }; test(aligned_copy_ctor); // CHECK: define void @_Z7forward17aligned_copy_ctor(%struct.aligned_copy_ctor* noalias sret %{{.*}}, %struct.aligned_copy_ctor* %{{.*}}) @@ -86,7 +90,7 @@ test(empty); // CHECK: declare void @_Z9def_emptyv() struct one_bitfield { - int d:3; + int d : 3; }; test(one_bitfield); // CHECK: define i32 @_Z7forward12one_bitfield(i32 returned %{{.*}}) |