diff options
Diffstat (limited to 'test/CodeGenCXX')
91 files changed, 2295 insertions, 266 deletions
diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp index abc700fef6c2..b2857ff41714 100644 --- a/test/CodeGenCXX/anonymous-namespaces.cpp +++ b/test/CodeGenCXX/anonymous-namespaces.cpp @@ -6,7 +6,8 @@ int f(); namespace { // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0 - // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11cE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_12c2E = internal global i32 0 // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0 int a = 0; @@ -15,6 +16,12 @@ namespace { static int c = f(); + // Note, we can't use an 'L' mangling for c or c2 (like GCC does) based on + // the 'static' specifier, because the variable can be redeclared without it. + extern int c2; + int g() { return c2; } + static int c2 = f(); + class D { static int d; }; diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp index 69fa61c2155c..e8c4480b4906 100644 --- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp +++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp @@ -80,37 +80,37 @@ namespace PR10512 { }; // CHECK-LABEL: define void @_ZN7PR105121AC2Ev - // CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] - // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]] - // CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] + // CHECK: [[THISADDR:%[a-zA-Z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] + // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-Z0-9.]+]], [[A]]** [[THISADDR]] + // CHECK-NEXT: [[THIS1:%[a-zA-Z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] // CHECK-NEXT: ret void A::A() {} // CHECK-LABEL: define void @_ZN7PR105121AC2Ei - // CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] - // CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i32 - // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]] - // CHECK-NEXT: store i32 [[X:%[a-zA-z0-9.]+]], i32* [[XADDR]] - // CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] + // CHECK: [[THISADDR:%[a-zA-Z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] + // CHECK-NEXT: [[XADDR:%[a-zA-Z0-9.]+]] = alloca i32 + // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-Z0-9.]+]], [[A]]** [[THISADDR]] + // CHECK-NEXT: store i32 [[X:%[a-zA-Z0-9.]+]], i32* [[XADDR]] + // CHECK-NEXT: [[THIS1:%[a-zA-Z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}} // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}} // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}} - // CHECK-NEXT: [[TMP:%[a-zA-z0-9.]+]] = load i32, i32* [[XADDR]] + // CHECK-NEXT: [[TMP:%[a-zA-Z0-9.]+]] = load i32, i32* [[XADDR]] // CHECK-NEXT: store i32 [[TMP]] // CHECK-NEXT: ret void A::A(int x) : x(x) { } // CHECK-LABEL: define void @_ZN7PR105121AC2El - // CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] - // CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i64 - // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]] - // CHECK-NEXT: store i64 [[X:%[a-zA-z0-9.]+]], i64* [[XADDR]] - // CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] + // CHECK: [[THISADDR:%[a-zA-Z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]] + // CHECK-NEXT: [[XADDR:%[a-zA-Z0-9.]+]] = alloca i64 + // CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-Z0-9.]+]], [[A]]** [[THISADDR]] + // CHECK-NEXT: store i64 [[X:%[a-zA-Z0-9.]+]], i64* [[XADDR]] + // CHECK-NEXT: [[THIS1:%[a-zA-Z0-9.]+]] = load [[A]]*, [[A]]** [[THISADDR]] // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}} // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 1}} // CHECK-NEXT: {{getelementptr inbounds.*i32 0, i32 0}} - // CHECK-NEXT: [[TMP:%[a-zA-z0-9.]+]] = load i64, i64* [[XADDR]] - // CHECK-NEXT: [[CONV:%[a-zA-z0-9.]+]] = trunc i64 [[TMP]] to i32 + // CHECK-NEXT: [[TMP:%[a-zA-Z0-9.]+]] = load i64, i64* [[XADDR]] + // CHECK-NEXT: [[CONV:%[a-zA-Z0-9.]+]] = trunc i64 [[TMP]] to i32 // CHECK-NEXT: store i32 [[CONV]] // CHECK-NEXT: ret void A::A(long y) : y(y) { } diff --git a/test/CodeGenCXX/arm64-constructor-return.cpp b/test/CodeGenCXX/arm64-constructor-return.cpp index 3adc1b7a280e..cbe66ab0e251 100644 --- a/test/CodeGenCXX/arm64-constructor-return.cpp +++ b/test/CodeGenCXX/arm64-constructor-return.cpp @@ -13,7 +13,7 @@ S::S() { // CHECK: %struct.S* @_ZN1SC2Ev(%struct.S* returned %this) // CHECK: %struct.S* @_ZN1SC1Ev(%struct.S* returned %this) -// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca %struct.S* +// CHECK: [[THISADDR:%[a-zA-Z0-9.]+]] = alloca %struct.S* // CHECK: store %struct.S* %this, %struct.S** [[THISADDR]] // CHECK: [[THIS1:%.*]] = load %struct.S*, %struct.S** [[THISADDR]] // CHECK: ret %struct.S* [[THIS1]] diff --git a/test/CodeGenCXX/atomic-align.cpp b/test/CodeGenCXX/atomic-align.cpp new file mode 100644 index 000000000000..9852ac38a6c8 --- /dev/null +++ b/test/CodeGenCXX/atomic-align.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s + +struct AM { + int f1, f2; +}; +alignas(8) AM m; +AM load1() { + AM am; + // m is declared to align to 8bytes, so generate load atomic instead + // of libcall. + // CHECK-LABEL: @_Z5load1v + // CHECK: load atomic {{.*}} monotonic + __atomic_load(&m, &am, 0); + return am; +} + +struct BM { + int f1; + alignas(8) AM f2; +}; +BM bm; +AM load2() { + AM am; + // BM::f2 is declared to align to 8bytes, so generate load atomic instead + // of libcall. + // CHECK-LABEL: @_Z5load2v + // CHECK: load atomic {{.*}} monotonic + __atomic_load(&bm.f2, &am, 0); + return am; +} diff --git a/test/CodeGenCXX/atomic-inline.cpp b/test/CodeGenCXX/atomic-inline.cpp new file mode 100644 index 000000000000..fe727589d2e2 --- /dev/null +++ b/test/CodeGenCXX/atomic-inline.cpp @@ -0,0 +1,69 @@ +// 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 +// Check the atomic code generation for cpu targets w/wo cx16 support. + +struct alignas(8) AM8 { + int f1, f2; +}; +AM8 m8; +AM8 load8() { + AM8 am; + // CHECK-LABEL: @_Z5load8v + // CHECK: load atomic i64, {{.*}} monotonic + // CORE2-LABEL: @_Z5load8v + // CORE2: load atomic i64, {{.*}} monotonic + __atomic_load(&m8, &am, 0); + return am; +} + +AM8 s8; +void store8() { + // CHECK-LABEL: @_Z6store8v + // CHECK: store atomic i64 {{.*}} monotonic + // CORE2-LABEL: @_Z6store8v + // CORE2: store atomic i64 {{.*}} monotonic + __atomic_store(&m8, &s8, 0); +} + +bool cmpxchg8() { + AM8 am; + // CHECK-LABEL: @_Z8cmpxchg8v + // CHECK: cmpxchg i64* {{.*}} monotonic + // CORE2-LABEL: @_Z8cmpxchg8v + // CORE2: cmpxchg i64* {{.*}} monotonic + return __atomic_compare_exchange(&m8, &s8, &am, 0, 0, 0); +} + +struct alignas(16) AM16 { + long f1, f2; +}; + +AM16 m16; +AM16 load16() { + AM16 am; + // CHECK-LABEL: @_Z6load16v + // CHECK: call void @__atomic_load + // CORE2-LABEL: @_Z6load16v + // CORE2: load atomic i128, {{.*}} monotonic + __atomic_load(&m16, &am, 0); + return am; +} + +AM16 s16; +void store16() { + // CHECK-LABEL: @_Z7store16v + // CHECK: call void @__atomic_store + // CORE2-LABEL: @_Z7store16v + // CORE2: store atomic i128 {{.*}} monotonic + __atomic_store(&m16, &s16, 0); +} + +bool cmpxchg16() { + AM16 am; + // CHECK-LABEL: @_Z9cmpxchg16v + // CHECK: call zeroext i1 @__atomic_compare_exchange + // CORE2-LABEL: @_Z9cmpxchg16v + // CORE2: cmpxchg i128* {{.*}} monotonic + return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0); +} + diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp index 5b7c7e6e46bb..37219d3f7abd 100644 --- a/test/CodeGenCXX/blocks.cpp +++ b/test/CodeGenCXX/blocks.cpp @@ -122,7 +122,6 @@ 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: load i8*, i8** // 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]]) diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index d58853c47f75..e8287538982b 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -16,6 +16,10 @@ struct S { // Check that type mismatch handler is not modified by ASan. // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} } +// CHECK: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) +// CHECK-X86: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) +// CHECK-X32: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) + struct T : S {}; // CHECK-LABEL: @_Z17reference_binding @@ -395,26 +399,93 @@ void downcast_reference(B &b) { // CHECK-NEXT: br i1 [[AND]] } -// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> -// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> -// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> +// +// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** {{.*}} to i64), i64 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i64)) to i32) }> +// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i32)) }> +// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i32)) }> void indirect_function_call(void (*p)(int)) { - // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>* + // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i32 }>* // Signature check - // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 0 + // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 0, i32 0 // CHECK-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] - // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 1413876459 + // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 846595819 // CHECK-NEXT: br i1 [[SIGCMP]] // RTTI pointer check - // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 1 - // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[RTTIPTR]] + // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 0, i32 1 + // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, i32* [[RTTIPTR]] + // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] to i64 + // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} to i64 + // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], [[FuncAddrInt]] + // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to i8** + // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], align 8 // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) // CHECK-NEXT: br i1 [[RTTICMP]] + p(42); } +namespace FunctionSanitizerVirtualCalls { +struct A { + virtual void f() {} + virtual void g() {} + void h() {} +}; + +struct B : virtual A { + virtual void b() {} + virtual void f(); + void g() final {} + static void q() {} +}; + +void B::f() {} + +void force_irgen() { + A a; + a.g(); + a.h(); + + B b; + b.f(); + b.b(); + b.g(); + B::q(); +} + +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv() +// CHECK: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv +// CHECK: prologue + +} + namespace UpcastPointerTest { struct S {}; struct T : S { double d; }; @@ -454,7 +525,7 @@ struct ThisAlign { void this_align_lambda_2(); }; void ThisAlign::this_align_lambda() { - // CHECK-LABEL: define {{.*}}@"_ZZN9ThisAlign17this_align_lambdaEvENK3$_0clEv" + // CHECK-LABEL: define internal %struct.ThisAlign* @"_ZZN9ThisAlign17this_align_lambdaEvENK3$_0clEv" // CHECK-SAME: (%{{.*}}* %[[this:[^)]*]]) // CHECK: %[[this_addr:.*]] = alloca // CHECK: store %{{.*}}* %[[this]], %{{.*}}** %[[this_addr]], @@ -555,7 +626,7 @@ namespace CopyValueRepresentation { } void ThisAlign::this_align_lambda_2() { - // CHECK-LABEL: define {{.*}}@"_ZZN9ThisAlign19this_align_lambda_2EvENK3$_1clEv" + // CHECK-LABEL: define internal void @"_ZZN9ThisAlign19this_align_lambda_2EvENK3$_1clEv" // CHECK-SAME: (%{{.*}}* %[[this:[^)]*]]) // CHECK: %[[this_addr:.*]] = alloca // CHECK: store %{{.*}}* %[[this]], %{{.*}}** %[[this_addr]], diff --git a/test/CodeGenCXX/cfi-blacklist.cpp b/test/CodeGenCXX/cfi-blacklist.cpp index af8a10601d29..c01e5fcd9260 100644 --- a/test/CodeGenCXX/cfi-blacklist.cpp +++ b/test/CodeGenCXX/cfi-blacklist.cpp @@ -1,6 +1,18 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s -// RUN: echo "type:std::*" > %t.txt -// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s + +// Check that blacklisting cfi and cfi-vcall work correctly +// RUN: echo "[cfi-vcall]" > %t.vcall.txt +// RUN: echo "type:std::*" >> %t.vcall.txt +// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s +// +// RUN: echo "[cfi]" > %t.cfi.txt +// RUN: echo "type:std::*" >> %t.cfi.txt +// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s + +// Check that blacklisting non-vcall modes does not affect vcalls +// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt +// RUN: echo "type:std::*" >> %t.other.txt +// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s struct S1 { virtual void f(); diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp index c3c6ed309cc6..5f5778fc1f7c 100644 --- a/test/CodeGenCXX/cfi-icall.cpp +++ b/test/CodeGenCXX/cfi-icall.cpp @@ -8,19 +8,22 @@ namespace { struct S {}; -void f(S *s) { +void f(S s) { } } void g() { - void (*fp)(S *) = f; - // CHECK: call i1 @llvm.type.test(i8* {{.*}}, metadata [[VOIDS:![0-9]+]]) - fp(0); + struct S s; + void (*fp)(S) = f; + // CHECK: call i1 @llvm.type.test(i8* {{.*}}, metadata [[VOIDS1:![0-9]+]]) + fp(s); } -// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fEPNS_1SE({{.*}} !type [[TS:![0-9]+]] -// MS: define internal void @"\01?f@?A@@YAXPEAUS@?A@@@Z"({{.*}} !type [[TS:![0-9]+]] +// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] +// MS: define internal void @"\01?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] -// CHECK: [[VOIDS]] = distinct !{} -// CHECK: [[TS]] = !{i64 0, [[VOIDS]]} +// CHECK: [[VOIDS1]] = distinct !{} +// CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]} +// CHECK: [[TS2]] = !{i64 0, [[VOIDS2:![0-9]+]]} +// CHECK: [[VOIDS2]] = distinct !{} diff --git a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp new file mode 100644 index 000000000000..3276d8f33edc --- /dev/null +++ b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template <typename T> +struct bar : virtual public foo { + void f() { + // CHECK: define{{.*}}@"\01?f@?$bar@Ubaz@@@@UEAAXXZ" + // Load "this", vbtable, vbase offset and vtable. + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" + static_cast<T&>(*this); + } +}; + +struct baz : public bar<baz> { + virtual ~baz() {} +}; + +int main() { + baz *z = new baz; + z->f(); +} diff --git a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp new file mode 100644 index 000000000000..ab610628232e --- /dev/null +++ b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-nvcall -fsanitize-trap=cfi-nvcall | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template <typename T> +struct bar : virtual public foo { + void f() {} +}; + +struct baz : public bar<baz> { + virtual ~baz() {} + void g() {} +}; + +void f(baz *z) { + // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z" + // Load z, vbtable, vbase offset and vtable. + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" + z->g(); +} diff --git a/test/CodeGenCXX/cfi-vcall-no-trap.cpp b/test/CodeGenCXX/cfi-vcall-no-trap.cpp new file mode 100644 index 000000000000..b7ef1426a91d --- /dev/null +++ b/test/CodeGenCXX/cfi-vcall-no-trap.cpp @@ -0,0 +1,15 @@ +// Only output llvm.assume(llvm.type.test()) if cfi-vcall is disabled and whole-program-vtables is enabled +// RUN: %clang_cc1 -flto -fvisibility hidden -fsanitize=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CFI %s +// RUN: %clang_cc1 -flto -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOCFI %s + +struct S1 { + virtual void f(); +}; + +// CHECK: define{{.*}}s1f +// CHECK: llvm.type.test +// CFI-NOT: llvm.assume +// NOCFI: llvm.assume +void s1f(S1 *s1) { + s1->f(); +} diff --git a/test/CodeGenCXX/cxx11-extern-constexpr.cpp b/test/CodeGenCXX/cxx11-extern-constexpr.cpp new file mode 100644 index 000000000000..6c520038e941 --- /dev/null +++ b/test/CodeGenCXX/cxx11-extern-constexpr.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CXX11 +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CXX17 + +struct A { + static const int Foo = 123; +}; +// CHECK: @_ZN1A3FooE = constant i32 123, align 4 +const int *p = &A::Foo; // emit available_externally +const int A::Foo; // convert to full definition + +struct PODWithInit { + int g = 42; + char h = 43; +}; +struct CreatePOD { + // Deferred initialization of the structure here requires changing + // the type of the global variable: the initializer list does not include + // the tail padding. + // CXX11: @_ZN9CreatePOD3podE = available_externally constant { i32, i8 } { i32 42, i8 43 }, + static constexpr PODWithInit pod{}; +}; +const int *p_pod = &CreatePOD::pod.g; + +struct Bar { + int b; +}; + +struct MutableBar { + mutable int b; +}; + +struct Foo { + // CXX11: @_ZN3Foo21ConstexprStaticMemberE = available_externally constant i32 42, + // CXX17: @_ZN3Foo21ConstexprStaticMemberE = linkonce_odr constant i32 42, + static constexpr int ConstexprStaticMember = 42; + // CHECK: @_ZN3Foo17ConstStaticMemberE = available_externally constant i32 43, + static const int ConstStaticMember = 43; + + // CXX11: @_ZN3Foo23ConstStaticStructMemberE = available_externally constant %struct.Bar { i32 44 }, + // CXX17: @_ZN3Foo23ConstStaticStructMemberE = linkonce_odr constant %struct.Bar { i32 44 }, + static constexpr Bar ConstStaticStructMember = {44}; + + // CXX11: @_ZN3Foo34ConstexprStaticMutableStructMemberE = external global %struct.MutableBar, + // CXX17: @_ZN3Foo34ConstexprStaticMutableStructMemberE = linkonce_odr global %struct.MutableBar { i32 45 }, + static constexpr MutableBar ConstexprStaticMutableStructMember = {45}; +}; +// CHECK: @_ZL15ConstStaticexpr = internal constant i32 46, +static constexpr int ConstStaticexpr = 46; +// CHECK: @_ZL9ConstExpr = internal constant i32 46, align 4 +static const int ConstExpr = 46; + +// CHECK: @_ZL21ConstexprStaticStruct = internal constant %struct.Bar { i32 47 }, +static constexpr Bar ConstexprStaticStruct = {47}; + +// CHECK: @_ZL28ConstexprStaticMutableStruct = internal global %struct.MutableBar { i32 48 }, +static constexpr MutableBar ConstexprStaticMutableStruct = {48}; + +void use(const int &); +void foo() { + use(Foo::ConstexprStaticMember); + use(Foo::ConstStaticMember); + use(Foo::ConstStaticStructMember.b); + use(Foo::ConstexprStaticMutableStructMember.b); + use(ConstStaticexpr); + use(ConstExpr); + use(ConstexprStaticStruct.b); + use(ConstexprStaticMutableStruct.b); +} diff --git a/test/CodeGenCXX/cxx11-special-members.cpp b/test/CodeGenCXX/cxx11-special-members.cpp index 037e59a6408f..96109ba5bac1 100644 --- a/test/CodeGenCXX/cxx11-special-members.cpp +++ b/test/CodeGenCXX/cxx11-special-members.cpp @@ -39,7 +39,9 @@ void f3() { C<0> a; D b; } -// CHECK: define {{.*}} @_ZN1CILi0EEC1Ev +// Trivial default ctor, might or might not be defined, but we must not expect +// someone else ot define it. +// CHECK-NOT: declare {{.*}} @_ZN1CILi0EEC1Ev // CHECK: define {{.*}} @_ZN1DC1Ev // CHECK: define {{.*}} @_ZN1BC2EOS_( diff --git a/test/CodeGenCXX/cxx1y-variable-template.cpp b/test/CodeGenCXX/cxx1y-variable-template.cpp index cd73817d8508..dd8f28e42992 100644 --- a/test/CodeGenCXX/cxx1y-variable-template.cpp +++ b/test/CodeGenCXX/cxx1y-variable-template.cpp @@ -18,6 +18,12 @@ int init_arr(); template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() }; int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>; +namespace PR35456 { +// CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0 +template<int> int n; +int *p = &n<0>; +} + // CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer // CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp index 437597d963b0..4c579978cb96 100644 --- a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -4,6 +4,8 @@ // RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s // RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefix=CHECK-MS + // Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z. // RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED // RUN: %clang_cc1 -std=c++1z -DUNALIGNED -fexceptions -fno-aligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED @@ -27,14 +29,28 @@ struct OVERALIGNED A { A(); int n[128]; }; // CHECK-LABEL: define {{.*}} @_Z2a0v() // CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32) // CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +// CHECK-MS-LABEL: define {{.*}} @"\01?a0@@YAPEAXXZ"() +// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32) +// CHECK-MS: cleanuppad +// CHECK-MS: call void @"\01??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) void *a0() { return new A; } +// FIXME: Why don't we call the sized array deallocation overload in this case? +// The size is known. +// // CHECK-LABEL: define {{.*}} @_Z2a1l( // CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32) // No array cookie. // CHECK-NOT: store // CHECK: invoke void @_ZN1AC1Ev( // CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +// CHECK-MS-LABEL: define {{.*}} @"\01?a1@@YAPEAXJ@Z"( +// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32) +// No array cookie. +// CHECK-MS-NOT: store +// CHECK-MS: invoke %struct.A* @"\01??0A@@QEAA@XZ"( +// CHECK-MS: cleanuppad +// CHECK-MS: call void @"\01??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) void *a1(long n) { return new A[n]; } // CHECK-LABEL: define {{.*}} @_Z2a2P1A( diff --git a/test/CodeGenCXX/cxx1z-copy-omission.cpp b/test/CodeGenCXX/cxx1z-copy-omission.cpp index 234e4b12589c..b33a21808175 100644 --- a/test/CodeGenCXX/cxx1z-copy-omission.cpp +++ b/test/CodeGenCXX/cxx1z-copy-omission.cpp @@ -6,6 +6,8 @@ struct A { A(const A&); ~A(); + operator bool(); + int arr[10]; }; @@ -79,3 +81,27 @@ void i() { // CHECK-LABEL: } } + +// CHECK-LABEL: define {{.*}} @_Z1jv( +void j() { + // CHECK: alloca %{{.*}}* + // CHECK: %[[OUTERTEMP:.*]] = alloca %{{.*}} + // CHECK: %[[INNERTEMP:.*]] = alloca %{{.*}} + // CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[INNERTEMP]], i32 1) + // CHECK: call zeroext i1 @_ZN1AcvbEv(%{{.*}} %[[INNERTEMP]]) + // CHECK: br i1 + // + // CHECK: call void @_ZN1AC1EOS_(%{{.*}} %[[OUTERTEMP]], %{{.*}} %[[INNERTEMP]]) + // CHECK: br label + // + // CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[OUTERTEMP]], i32 2) + // CHECK: br label + // + // CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[INNERTEMP]]) + A &&a = A(1) ?: A(2); + + // CHECK: call void @_Z1iv() + i(); + + // CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[OUTERTEMP]]) +} diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp index 183709373d12..2d16acd8a8c2 100644 --- a/test/CodeGenCXX/cxx1z-inline-variables.cpp +++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp @@ -31,18 +31,28 @@ struct compat { static constexpr int b = 2; static constexpr int c = 3; static inline constexpr int d = 4; + static const int e = 5; + static const int f = 6; + static const int g = 7; }; const int &compat_use_before_redecl = compat::b; const int compat::a; const int compat::b; const int compat::c; const int compat::d; +const int compat::e; +constexpr int compat::f; +constexpr inline int compat::g; const int &compat_use_after_redecl1 = compat::c; const int &compat_use_after_redecl2 = compat::d; -// CHECK: @_ZN6compat1bE = weak_odr constant i32 2 -// CHECK: @_ZN6compat1aE = weak_odr constant i32 1 -// CHECK: @_ZN6compat1cE = weak_odr constant i32 3 -// CHECK: @_ZN6compat1dE = linkonce_odr constant i32 4 +const int &compat_use_after_redecl3 = compat::g; +// CHECK-DAG: @_ZN6compat1bE = weak_odr constant i32 2 +// CHECK-DAG: @_ZN6compat1aE = weak_odr constant i32 1 +// CHECK-DAG: @_ZN6compat1cE = weak_odr constant i32 3 +// CHECK-DAG: @_ZN6compat1dE = linkonce_odr constant i32 4 +// CHECK-DAG: @_ZN6compat1eE = constant i32 5 +// CHECK-DAG: @_ZN6compat1fE = weak_odr constant i32 6 +// CHECK-DAG: @_ZN6compat1gE = linkonce_odr constant i32 7 template<typename T> struct X { static int a; @@ -57,6 +67,18 @@ int &use3 = X<int>::a; template<> int X<int>::b = 20; template<> inline int X<int>::c = 30; +template<typename T> struct Y; +template<> struct Y<int> { + static constexpr int a = 123; + static constexpr int b = 456; + static constexpr int c = 789; +}; +// CHECK: @_ZN1YIiE1aE = weak_odr constant i32 123 +constexpr int Y<int>::a; +// CHECK: @_ZN1YIiE1bE = linkonce_odr constant i32 456 +const int &yib = Y<int>::b; +// CHECK-NOT: @_ZN1YIiE1cE + // CHECK-LABEL: define {{.*}}global_var_init // CHECK: call i32 @_Z1fv diff --git a/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/test/CodeGenCXX/cxx2a-destroying-delete.cpp new file mode 100644 index 000000000000..2e4d40715e15 --- /dev/null +++ b/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -0,0 +1,161 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-windows -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-MSABI + +namespace std { + using size_t = decltype(sizeof(0)); + enum class align_val_t : size_t; + struct destroying_delete_t {}; +} + +struct A { + void *data; + ~A(); + void operator delete(A*, std::destroying_delete_t); +}; +void delete_A(A *a) { delete a; } +// CHECK-LABEL: define {{.*}}delete_A +// CHECK: %[[a:.*]] = load +// CHECK: icmp eq %{{.*}} %[[a]], null +// CHECK: br i1 +// +// Ensure that we call the destroying delete and not the destructor. +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) +// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-NOT: call +// CHECK: } + +struct B { + virtual ~B(); + void operator delete(B*, std::destroying_delete_t); +}; +void delete_B(B *b) { delete b; } +// CHECK-LABEL: define {{.*}}delete_B +// CHECK: %[[b:.*]] = load +// CHECK: icmp eq %{{.*}} %[[b]], null +// CHECK: br i1 +// +// Ensure that we call the virtual destructor and not the operator delete. +// CHECK-NOT: call +// CHECK: %[[VTABLE:.*]] = load +// CHECK: %[[DTOR:.*]] = load +// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[b]] +// CHECK-MSABI-SAME: , i32 1) +// CHECK-NOT: call +// CHECK: } + +struct Padding { + virtual void f(); +}; + +struct C : Padding, A {}; +void delete_C(C *c) { delete c; } +// Check that we perform a derived-to-base conversion on the parameter to 'operator delete'. +// CHECK-LABEL: define {{.*}}delete_C +// CHECK: %[[c:.*]] = load +// CHECK: icmp eq %{{.*}} %[[c]], null +// CHECK: br i1 +// +// CHECK: %[[base:.*]] = getelementptr {{.*}}, i64 8 +// CHECK: %[[castbase:.*]] = bitcast {{.*}} %[[base]] +// +// CHECK: %[[a:.*]] = phi {{.*}} %[[castbase]] +// CHECK: icmp eq %{{.*}} %[[a]], null +// CHECK: br i1 +// +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) +// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-NOT: call +// CHECK: } + +struct VDel { virtual ~VDel(); }; +struct D : Padding, VDel, B {}; +void delete_D(D *d) { delete d; } +// CHECK-LABEL: define {{.*}}delete_D +// CHECK: %[[d:.*]] = load +// CHECK: icmp eq %{{.*}} %[[d]], null +// CHECK: br i1 +// +// CHECK-NOT: call +// CHECK: %[[VTABLE:.*]] = load +// CHECK: %[[DTOR:.*]] = load +// +// For MS, we don't add a new vtable slot to the primary vtable for the virtual +// destructor. Instead we cast to the VDel base class. +// CHECK-MSABI: bitcast {{.*}} %[[d]] +// CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8 +// CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8* +// +// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]] +// CHECK-MSABI-SAME: , i32 1) +// CHECK-NOT: call +// CHECK: } + +struct E { void *data; }; +struct F { void operator delete(F *, std::destroying_delete_t, std::size_t, std::align_val_t); void *data; }; +struct alignas(16) G : E, F { void *data; }; + +void delete_G(G *g) { delete g; } +// CHECK-LABEL: define {{.*}}delete_G +// CHECK-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16) +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) +// CHECK-NOT: call +// CHECK: } + +void call_in_dtor(); + +struct H : G { virtual ~H(); } h; +H::~H() { call_in_dtor(); } +// CHECK-ITANIUM-LABEL: define void @_ZN1HD0Ev( +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: getelementptr {{.*}}, i64 24 +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 48, i64 16) +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: } + +// CHECK-MSABI: define {{.*}} @"\01??_GH@@UEAAPEAXI@Z"( +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: load i32 +// CHECK-MSABI: icmp eq i32 {{.*}}, 0 +// CHECK-MSABI: br i1 +// +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) +// CHECK-MSABI: br label %[[RETURN:.*]] +// +// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"( +// CHECK-MSABI: br label %[[RETURN]] +// +// CHECK-MSABI: } + +struct I : H { virtual ~I(); alignas(32) char buffer[32]; } i; +I::~I() { call_in_dtor(); } +// CHECK-ITANIUM-LABEL: define void @_ZN1ID0Ev( +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: getelementptr {{.*}}, i64 24 +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 96, i64 32) +// CHECK-ITANIUM-NOT: call +// CHECK-ITANIUM: } + +// CHECK-MSABI: define {{.*}} @"\01??_GI@@UEAAPEAXI@Z"( +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: load i32 +// CHECK-MSABI: icmp eq i32 {{.*}}, 0 +// CHECK-MSABI: br i1 +// +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: getelementptr {{.*}}, i64 24 +// CHECK-MSABI-NOT: call{{ }} +// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) +// CHECK-MSABI: br label %[[RETURN:.*]] +// +// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"( +// CHECK-MSABI: br label %[[RETURN]] +// +// CHECK-MSABI: } diff --git a/test/CodeGenCXX/cxx2a-three-way-comparison.cpp b/test/CodeGenCXX/cxx2a-three-way-comparison.cpp new file mode 100644 index 000000000000..fd72d4a39cb3 --- /dev/null +++ b/test/CodeGenCXX/cxx2a-three-way-comparison.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s --check-prefix=ITANIUM +// RUN: not %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %ms_abi_triple 2>&1 | FileCheck %s --check-prefix=MSABI +// RUN: not %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple -DBUILTIN 2>&1 | FileCheck %s --check-prefix=BUILTIN +// MSABI: cannot mangle this three-way comparison operator yet + +struct A { + void operator<=>(int); +}; + +// ITANIUM: define {{.*}}@_ZN1AssEi( +void A::operator<=>(int) {} + +// ITANIUM: define {{.*}}@_Zssi1A( +void operator<=>(int, A) {} + +int operator<=>(A, A); + +// ITANIUM: define {{.*}}_Z1f1A( +int f(A a) { + // ITANIUM: %[[RET:.*]] = call {{.*}}_Zss1AS_( + // ITANIUM: ret i32 %[[RET]] + return a <=> a; +} + +#ifdef BUILTIN +void builtin(int a) { + a <=> a; // BUILTIN: cannot compile this scalar expression yet +} +#endif diff --git a/test/CodeGenCXX/debug-info-anon-namespace.cpp b/test/CodeGenCXX/debug-info-anon-namespace.cpp index 3f4ef2a38360..56c8528abdee 100644 --- a/test/CodeGenCXX/debug-info-anon-namespace.cpp +++ b/test/CodeGenCXX/debug-info-anon-namespace.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-scei-ps4 -O0 %s -o - | FileCheck --check-prefix=PS4 %s -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-unknown-linux-gnu -O0 %s -o - | FileCheck --check-prefix=NON-PS4 %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -dwarf-explicit-import -O0 %s -o - | FileCheck --check-prefix=IMPORT %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -O0 %s -o - | FileCheck --check-prefix=NOIMPORT %s namespace { @@ -17,11 +17,9 @@ namespace int *b1 = &a1; int *b2 = &a2; - -// PS4: [[NS:![0-9]+]] = !DINamespace -// PS4: [[CU:![0-9]+]] = distinct !DICompileUnit -// PS4: [[NS2:![0-9]+]] = !DINamespace -// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[NS]], file: {{![0-9]+}}) -// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[NS]], entity: [[NS2]], file: {{![0-9]+}}, line: {{[0-9]+}}) -// NON-PS4-NOT: !DIImportedEntity - +// IMPORT: [[NS:![0-9]+]] = !DINamespace +// IMPORT: [[CU:![0-9]+]] = distinct !DICompileUnit +// IMPORT: [[NS2:![0-9]+]] = !DINamespace +// IMPORT: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[NS]], file: {{![0-9]+}}) +// IMPORT: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[NS]], entity: [[NS2]], file: {{![0-9]+}}, line: {{[0-9]+}}) +// NOIMPORT-NOT: !DIImportedEntity diff --git a/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/test/CodeGenCXX/debug-info-codeview-display-name.cpp index b1b5a1e9acb8..17049d506fa6 100644 --- a/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ b/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s \ // RUN: -o - -triple=x86_64-pc-win32 -std=c++98 | \ -// RUN: grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \ +// RUN: grep 'DISubprogram\|DICompositeType' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=UNQUAL // RUN: %clang_cc1 -fblocks -debug-info-kind=line-tables-only -gcodeview -emit-llvm %s \ // RUN: -o - -triple=x86_64-pc-win32 -std=c++98 | \ @@ -91,3 +91,8 @@ void fn_tmpl() {} template void fn_tmpl<int, freefunc>(); // CHECK-DAG: "fn_tmpl<int,&freefunc>" + +template <typename A, typename B, typename C> struct ClassTemplate { A a; B b; C c; }; +ClassTemplate<char, short, ClassTemplate<int, int, int> > f; +// This will only show up in normal debug builds. +// UNQUAL-DAG: "ClassTemplate<char,short,ClassTemplate<int,int,int> >" diff --git a/test/CodeGenCXX/debug-info-codeview-nested-types.cpp b/test/CodeGenCXX/debug-info-codeview-nested-types.cpp new file mode 100644 index 000000000000..7c8f78e7a001 --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-nested-types.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s + +struct HasNested { + enum InnerEnum { _BUF_SIZE = 1 }; + typedef int InnerTypedef; + enum { InnerEnumerator = 2 }; + struct InnerStruct { }; +}; +HasNested f; + +// CHECK: ![[INNERENUM:[0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "InnerEnum", {{.*}}) +// CHECK: ![[HASNESTED:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasNested", +// CHECK-SAME: elements: ![[MEMBERS:[0-9]+]], +// +// CHECK: ![[MEMBERS]] = !{![[INNERENUM]], ![[INNERTYPEDEF:[0-9]+]], ![[UNNAMEDENUM:[0-9]+]], ![[INNERSTRUCT:[0-9]+]]} +// +// CHECK: ![[INNERTYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "InnerTypedef", scope: ![[HASNESTED]]{{.*}}) +// +// CHECK: ![[UNNAMEDENUM]] = !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[HASNESTED]], +// CHECK-SAME: elements: ![[UNNAMEDMEMBERS:[0-9]+]], +// CHECK: ![[UNNAMEDMEMBERS]] = !{![[INNERENUMERATOR:[0-9]+]]} +// CHECK: ![[INNERENUMERATOR]] = !DIEnumerator(name: "InnerEnumerator", value: 2) +// +// CHECK: ![[INNERSTRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "InnerStruct" +// CHECK-SAME: flags: DIFlagFwdDecl diff --git a/test/CodeGenCXX/debug-info-fwd-template-param.cpp b/test/CodeGenCXX/debug-info-fwd-template-param.cpp new file mode 100644 index 000000000000..2983f842744a --- /dev/null +++ b/test/CodeGenCXX/debug-info-fwd-template-param.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple=%itanium_abi_triple -debug-info-kind=limited -debug-forward-template-params -emit-llvm -o - | FileCheck --check-prefix=CHILD %s +// RUN: %clang_cc1 %s -triple=%itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - | FileCheck --check-prefix=NONE %s +// A DWARF forward declaration of a template instantiation should have template +// parameter children (if we ask for them). + +template<typename T> class A; +A<int> *p; + +// CHILD: !DICompositeType(tag: DW_TAG_class_type, name: "A<int>" +// CHILD-SAME: flags: DIFlagFwdDecl +// CHILD-SAME: templateParams: [[PARAM_LIST:![0-9]*]] +// CHILD: [[PARAM_LIST]] = !{[[PARAM:![0-9]*]]} +// CHILD: [[PARAM]] = !DITemplateTypeParameter(name: "T", +// CHILD-SAME: type: [[BTYPE:![0-9]*]] +// CHILD: [[BTYPE]] = !DIBasicType(name: "int" + +// NONE: !DICompositeType(tag: DW_TAG_class_type, name: "A<int>" +// NONE-SAME: flags: DIFlagFwdDecl +// NONE-NOT: templateParams: +// NONE-SAME: ) diff --git a/test/CodeGenCXX/debug-info-inheriting-constructor.cpp b/test/CodeGenCXX/debug-info-inheriting-constructor.cpp index e3708e2080f0..8e47a0da6dff 100644 --- a/test/CodeGenCXX/debug-info-inheriting-constructor.cpp +++ b/test/CodeGenCXX/debug-info-inheriting-constructor.cpp @@ -13,7 +13,7 @@ A::A(int i, ...) {} // CHECK: call void @llvm.dbg.declare // CHECK-NOT ret void // CHECK: call void @llvm.dbg.declare(metadata %{{.*}}** %{{[^,]+}}, -// CHECK-SAME: metadata ![[THIS:[0-9]+]], metadata !{{[0-9]+}}), !dbg ![[LOC:[0-9]+]] +// CHECK-SAME: metadata ![[THIS:[0-9]+]], metadata !DIExpression()), !dbg ![[LOC:[0-9]+]] // CHECK: ret void, !dbg ![[NOINL:[0-9]+]] // CHECK: ![[FOO:.*]] = distinct !DISubprogram(name: "foo" // CHECK-DAG: ![[A:.*]] = distinct !DISubprogram(name: "A", linkageName: "_ZN1BCI11AEiz" diff --git a/test/CodeGenCXX/debug-info-inlined.cpp b/test/CodeGenCXX/debug-info-inlined.cpp index 9969ef79ca7e..53e2cc9289c2 100644 --- a/test/CodeGenCXX/debug-info-inlined.cpp +++ b/test/CodeGenCXX/debug-info-inlined.cpp @@ -1,45 +1,29 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-pc-windows-msvc19.0.24213 -gcodeview -debug-info-kind=limited -std=c++14 %s -o - | FileCheck %s // PR33997. -struct already_AddRefed { - ~already_AddRefed(); +struct WithDtor { + ~WithDtor(); }; -struct RefPtr { - operator int *(); +struct Base { + Base(WithDtor); }; -struct ServoCssRulesStrong { - already_AddRefed Consume(); +class Forward : Base { + using Base::Base; }; -struct GroupRule { - GroupRule(already_AddRefed); +class A : Forward { + A(); }; -class ConditionRule : GroupRule { - using GroupRule::GroupRule; +class B : Forward { + B(); }; -class CSSMediaRule : ConditionRule { - using ConditionRule::ConditionRule; -}; -class CSSMozDocumentRule : ConditionRule { - using ConditionRule::ConditionRule; -}; -class ServoDocumentRule : CSSMozDocumentRule { - ServoDocumentRule(RefPtr); -}; -class ServoMediaRule : CSSMediaRule { - ServoMediaRule(RefPtr); -}; -ServoCssRulesStrong Servo_MediaRule_GetRules(int *); -ServoCssRulesStrong Servo_DocumentRule_GetRules(int *); -ServoDocumentRule::ServoDocumentRule(RefPtr aRawRule) - : CSSMozDocumentRule(Servo_DocumentRule_GetRules(aRawRule).Consume()) {} +A::A() : Forward(WithDtor()) {} -ServoMediaRule::ServoMediaRule(RefPtr aRawRule) - : CSSMediaRule(Servo_MediaRule_GetRules(aRawRule).Consume()) {} +B::B() : Forward(WithDtor()) {} -// CHECK: define{{.*}}ServoMediaRule +// CHECK: define{{.*}}A // CHECK-NOT: {{ ret }} -// CHECK: store %class.ConditionRule* % -// CHECK-SAME: %class.ConditionRule** % +// CHECK: store %class.Forward* % +// CHECK-SAME: %class.Forward** % // CHECK-SAME: !dbg ![[INL:[0-9]+]] -// CHECK: ![[INL]] = !DILocation(line: 16, scope: ![[SP:[0-9]+]], inlinedAt: -// CHECK: ![[SP]] = distinct !DISubprogram(name: "GroupRule", {{.*}}isDefinition: true +// CHECK: ![[INL]] = !DILocation(line: 10, scope: ![[SP:[0-9]+]], inlinedAt: +// CHECK: ![[SP]] = distinct !DISubprogram(name: "Base", {{.*}}isDefinition: true diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index e0f9a284f2cf..af7103e57528 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -20,6 +20,7 @@ union { class A { protected: void foo(int, A, decltype(u)); + void bar(); }; void A::foo(int, A, decltype(u)) { @@ -29,3 +30,5 @@ A a; int A::*x = 0; int (A::*y)(int) = 0; + +void A::bar() { foo(0, *this, u); } diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp index 1bf8bab5f41c..e83d7e94230d 100644 --- a/test/CodeGenCXX/debug-info-ms-abi.cpp +++ b/test/CodeGenCXX/debug-info-ms-abi.cpp @@ -6,6 +6,7 @@ struct Foo { virtual void f(); virtual void g(); virtual void h(); + static void i(int, int); struct Nested {}; }; Foo f; @@ -18,7 +19,7 @@ Foo::Nested n; // CHECK-SAME: elements: ![[elements:[0-9]+]] // CHECK-SAME: identifier: ".?AUFoo@@" -// CHECK: ![[elements]] = !{![[vshape:[0-9]+]], ![[vptr:[0-9]+]], ![[Nested]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]]} +// CHECK: ![[elements]] = !{![[vshape:[0-9]+]], ![[vptr:[0-9]+]], ![[Nested]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]], ![[i:[0-9]+]]} // CHECK: ![[vshape]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: null, size: 96) @@ -38,3 +39,9 @@ Foo::Nested n; // CHECK: ![[h]] = !DISubprogram(name: "h", // CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// 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) diff --git a/test/CodeGenCXX/debug-info-nested-exprs.cpp b/test/CodeGenCXX/debug-info-nested-exprs.cpp new file mode 100644 index 000000000000..bd70373e2285 --- /dev/null +++ b/test/CodeGenCXX/debug-info-nested-exprs.cpp @@ -0,0 +1,202 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited \ +// RUN: -std=c++11 -gcodeview -emit-llvm -o - %s \ +// RUN: | FileCheck -check-prefix=NONEST %s +// RUN: %clang_cc1 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited \ +// RUN: -std=c++11 -gcodeview -dwarf-column-info -emit-llvm -o - %s \ +// RUN: | FileCheck -check-prefix=COLUMNS %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -debug-info-kind=limited \ +// RUN: -std=c++11 -emit-llvm -o - %s | FileCheck -check-prefix=NESTED %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -debug-info-kind=limited \ +// RUN: -std=c++11 -dwarf-column-info -emit-llvm -o - %s \ +// RUN: | FileCheck -check-prefix=COLUMNS %s + +class Foo { +public: + static Foo create(); + void func(); + int *begin(); + int *end(); +}; + +int bar(int x, int y); +int baz(int x, int y); +int qux(int x, int y); +int onearg(int x); +int noargs(); +int noargs1(); +Foo range(int x); + +int foo(int x, int y, int z) { + int a = bar(x, y) + + baz(x, z) + + qux(y, z); + // NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[LOC:[0-9]+]] + // NONEST: call i32 @{{.*}}baz{{.*}}, !dbg ![[LOC]] + // NONEST: call i32 @{{.*}}qux{{.*}}, !dbg ![[LOC]] + // NONEST: store i32 {{.*}}, i32* %a,{{.*}} !dbg ![[LOC]] + // NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[BAR:[0-9]+]] + // NESTED: call i32 @{{.*}}baz{{.*}}, !dbg ![[BAZ:[0-9]+]] + // NESTED: call i32 @{{.*}}qux{{.*}}, !dbg ![[QUX:[0-9]+]] + // NESTED: store i32 {{.*}}, i32* %a,{{.*}} !dbg ![[BAR]] + // COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[BAR:[0-9]+]] + // COLUMNS: call i32 @{{.*}}baz{{.*}}, !dbg ![[BAZ:[0-9]+]] + // COLUMNS: call i32 @{{.*}}qux{{.*}}, !dbg ![[QUX:[0-9]+]] + // COLUMNS: store i32 {{.*}}, i32* %a,{{.*}} !dbg ![[DECLA:[0-9]+]] + + int i = 1, b = 0, c = 0; + // NONEST: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]] + // NONEST: store i32 0, i32* %b,{{.*}} !dbg ![[ILOC]] + // NONEST: store i32 0, i32* %c,{{.*}} !dbg ![[ILOC]] + // NESTED: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]] + // NESTED: store i32 0, i32* %b,{{.*}} !dbg ![[ILOC]] + // NESTED: store i32 0, i32* %c,{{.*}} !dbg ![[ILOC]] + // COLUMNS: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]] + // COLUMNS: store i32 0, i32* %b,{{.*}} !dbg ![[BLOC:[0-9]+]] + // COLUMNS: store i32 0, i32* %c,{{.*}} !dbg ![[CLOC:[0-9]+]] + + while (i > 0) { + b = bar(a, b); + --i; + } + // NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]] + // NONEST: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]] + // NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]] + // NESTED: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]] + // COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]] + + for (i = 0; i < 1; i++) { + b = bar(a, b); + c = qux(a, c); + } + // NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]] + // NONEST: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]] + // NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]] + // NESTED: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]] + // COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]] + // COLUMNS: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]] + + if (a < b) { + int t = a; + a = b; + b = t; + } + // NONEST: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]] + // NONEST: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]] + // NONEST: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]] + // NESTED: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]] + // NESTED: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]] + // NESTED: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]] + + int d = onearg( + noargs()); + // NONEST: call i32 @{{.*}}noargs{{.*}}, !dbg ![[DECLD:[0-9]+]] + // NONEST: call i32 @{{.*}}onearg{{.*}}, !dbg ![[DECLD]] + // NONEST: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[DECLD]] + // NESTED: call i32 @{{.*}}noargs{{.*}}, !dbg ![[DNOARGS:[0-9]+]] + // NESTED: call i32 @{{.*}}onearg{{.*}}, !dbg ![[DECLD:[0-9]+]] + // NESTED: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[DECLD]] + // COLUMNS: call i32 @{{.*}}noargs{{.*}}, !dbg ![[DNOARGS:[0-9]+]] + // COLUMNS: call i32 @{{.*}}onearg{{.*}}, !dbg ![[DONEARG:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[DECLD:[0-9]+]] + + d = onearg(noargs()); + // NONEST: call i32 @{{.*}}noargs{{.*}}, !dbg ![[SETD:[0-9]+]] + // NONEST: call i32 @{{.*}}onearg{{.*}}, !dbg ![[SETD]] + // NONEST: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[SETD]] + // NESTED: call i32 @{{.*}}noargs{{.*}}, !dbg ![[SETD:[0-9]+]] + // NESTED: call i32 @{{.*}}onearg{{.*}}, !dbg ![[SETD]] + // NESTED: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[SETD]] + // COLUMNS: call i32 @{{.*}}noargs{{.*}}, !dbg ![[SETDNOARGS:[0-9]+]] + // COLUMNS: call i32 @{{.*}}onearg{{.*}}, !dbg ![[SETDONEARG:[0-9]+]] + // COLUMNS: store i32 %{{[^,]+}}, i32* %d,{{.*}} !dbg ![[SETD:[0-9]+]] + + for (const auto x : range(noargs())) noargs1(); + // NONEST: call i32 @{{.*}}noargs{{.*}}, !dbg ![[RANGEFOR:[0-9]+]] + // NONEST: call {{.+}} @{{.*}}range{{.*}}, !dbg ![[RANGEFOR]] + // NONEST: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[RANGEFOR_BODY:[0-9]+]] + // NESTED: call i32 @{{.*}}noargs{{.*}}, !dbg ![[RANGEFOR:[0-9]+]] + // NESTED: call {{.+}} @{{.*}}range{{.*}}, !dbg ![[RANGEFOR]] + // NESTED: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[RANGEFOR_BODY:[0-9]+]] + // COLUMNS: call i32 @{{.*}}noargs{{.*}}, !dbg ![[RANGEFOR_NOARGS:[0-9]+]] + // COLUMNS: call {{.+}} @{{.*}}range{{.*}}, !dbg ![[RANGEFOR_RANGE:[0-9]+]] + // COLUMNS: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[RANGEFOR_BODY:[0-9]+]] + + if (noargs() && noargs1()) { + Foo::create().func(); + } + // NONEST: call i32 @{{.*}}noargs{{.*}}, !dbg ![[AND:[0-9]+]] + // NONEST: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[AND]] + // NONEST: call {{.+}} @{{.*}}create{{.*}}, !dbg ![[AND_BODY:[0-9]+]] + // NONEST: call void @{{.*}}func{{.*}}, !dbg ![[AND_BODY]] + // NESTED: call i32 @{{.*}}noargs{{.*}}, !dbg ![[AND:[0-9]+]] + // NESTED: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[AND]] + // NESTED: call {{.+}} @{{.*}}create{{.*}}, !dbg ![[AND_BODY:[0-9]+]] + // NESTED: call void @{{.*}}func{{.*}}, !dbg ![[AND_BODY]] + // COLUMNS: call i32 @{{.*}}noargs{{.*}}, !dbg ![[ANDLHS:[0-9]+]] + // COLUMNS: call i32 @{{.*}}noargs1{{.*}}, !dbg ![[ANDRHS:[0-9]+]] + // COLUMNS: call {{.+}} @{{.*}}create{{.*}}, !dbg ![[AND_CREATE:[0-9]+]] + // COLUMNS: call void @{{.*}}func{{.*}}, !dbg ![[AND_FUNC:[0-9]+]] + + return a - + (b * z); + // NONEST: mul nsw i32 {{.*}}, !dbg ![[RETLOC:[0-9]+]] + // NONEST: sub nsw i32 {{.*}}, !dbg ![[RETLOC]] + // NONEST: ret i32 {{.*}}, !dbg ![[RETLOC]] + // NESTED: mul nsw i32 {{.*}}, !dbg ![[RETMUL:[0-9]+]] + // NESTED: sub nsw i32 {{.*}}, !dbg ![[RETSUB:[0-9]+]] + // NESTED: ret i32 {{.*}}, !dbg ! + // COLUMNS: mul nsw i32 {{.*}}, !dbg ![[RETMUL:[0-9]+]] + // COLUMNS: sub nsw i32 {{.*}}, !dbg ![[RETSUB:[0-9]+]] + // COLUMNS: ret i32 {{.*}}, !dbg ! +} + +// NONEST: ![[WHILE1]] = !DILocation( +// NONEST: ![[WHILE2]] = !DILocation( +// NONEST: ![[FOR1]] = !DILocation( +// NONEST: ![[FOR2]] = !DILocation( +// NONEST: ![[IF1]] = !DILocation( +// NONEST: ![[IF2]] = !DILocation( +// NONEST: ![[IF3]] = !DILocation( +// NONEST: ![[RANGEFOR]] = !DILocation( +// NONEST-SAME: line: [[RANGEFOR_LINE:[0-9]+]] +// NONEST: ![[RANGEFOR_BODY]] = !DILocation( +// NONEST-SAME: line: [[RANGEFOR_LINE]] + +// NESTED: ![[BAR]] = !DILocation( +// NESTED: ![[BAZ]] = !DILocation( +// NESTED: ![[QUX]] = !DILocation( +// NESTED: ![[DECLD]] = !DILocation +// NESTED: ![[DNOARGS]] = !DILocation +// NESTED: ![[RANGEFOR]] = !DILocation( +// NESTED-SAME: line: [[RANGEFOR_LINE:[0-9]+]] +// NESTED: ![[RANGEFOR_BODY]] = !DILocation( +// NESTED-SAME: line: [[RANGEFOR_LINE]] +// NESTED: ![[RETSUB]] = !DILocation( +// NESTED: ![[RETMUL]] = !DILocation( + +// COLUMNS: ![[DECLA]] = !DILocation( +// COLUMNS: ![[BAR]] = !DILocation( +// COLUMNS: ![[BAZ]] = !DILocation( +// COLUMNS: ![[QUX]] = !DILocation( +// COLUMNS: ![[ILOC]] = !DILocation( +// COLUMNS: ![[BLOC]] = !DILocation( +// COLUMNS: ![[CLOC]] = !DILocation( +// COLUMNS: ![[DECLD]] = !DILocation( +// COLUMNS: ![[DNOARGS]] = !DILocation( +// COLUMNS: ![[DONEARG]] = !DILocation( +// COLUMNS: ![[SETDNOARGS]] = !DILocation( +// COLUMNS: ![[SETDONEARG]] = !DILocation( +// COLUMNS: ![[SETD]] = !DILocation( +// COLUMNS: ![[RANGEFOR_NOARGS]] = !DILocation( +// COLUMNS: ![[RANGEFOR_RANGE]] = !DILocation( +// COLUMNS: ![[RANGEFOR_BODY]] = !DILocation( +// COLUMNS: ![[ANDLHS]] = !DILocation +// COLUMNS: ![[ANDRHS]] = !DILocation +// COLUMNS: ![[AND_CREATE]] = !DILocation +// COLUMNS: ![[AND_FUNC]] = !DILocation +// COLUNMS: ![[RETSUB]] = !DILocation( +// COLUMNS: ![[RETMUL]] = !DILocation( diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index c777ccb2aba2..3537754ced76 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -32,7 +32,7 @@ public: // why the definition of "a" comes before the declarations while // "b" and "c" come after. -// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]]) +// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]], expr: !DIExpression()) // CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a", // CHECK-SAME: declaration: ![[DECL_A:[0-9]+]]) // @@ -45,7 +45,7 @@ public: // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var" int C::a = 4; -// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]]) +// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]], expr: !DIExpression()) // CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b", // CHECK-SAME: declaration: ![[DECL_B:[0-9]+]]) // CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b" @@ -93,7 +93,7 @@ int C::a = 4; // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember) int C::b = 2; -// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]]) +// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]], expr: !DIExpression()) // CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]]) int C::c = 1; diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index 2b840745ffeb..a6aa1a05a256 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -19,7 +19,7 @@ inline int add3(int x) { } // The compile unit pulls in the global variables first. -// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]]) +// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression()) // CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", // CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index 54fac0b36eec..0c3414516215 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -25,7 +25,7 @@ struct TC { int glb; void func(); -// CHECK: [[TCI]] = !DIGlobalVariableExpression(var: [[TCIV:.*]]) +// CHECK: [[TCI]] = !DIGlobalVariableExpression(var: [[TCIV:.*]], expr: !DIExpression()) // CHECK: [[TCIV]] = distinct !DIGlobalVariable(name: "tci", // CHECK-SAME: type: ![[TCNESTED:[0-9]+]] // CHECK: ![[TCNESTED]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "nested", @@ -84,7 +84,7 @@ TC // CHECK: [[TCARG7_3]] = !DITemplateValueParameter(type: [[INT]], value: i32 3) 3>::nested tci; -// CHECK: [[TCN]] = !DIGlobalVariableExpression(var: [[TCNV:.*]]) +// CHECK: [[TCN]] = !DIGlobalVariableExpression(var: [[TCNV:.*]], expr: !DIExpression()) // CHECK: [[TCNV]] = distinct !DIGlobalVariable(name: "tcn" // CHECK-SAME: type: ![[TCNT:[0-9]+]] TC @@ -125,7 +125,7 @@ template <template <typename> class tmpl, int &lvr, int &&rvr> struct NN { }; -// CHECK: [[NN]] = !DIGlobalVariableExpression(var: [[NNV:.*]]) +// CHECK: [[NN]] = !DIGlobalVariableExpression(var: [[NNV:.*]], expr: !DIExpression()) // CHECK: [[NNV]] = distinct !DIGlobalVariable(name: "nn" // CHECK-SAME: type: ![[NNT:[0-9]+]] diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 2b86150b52b5..6d6d0c7d19cf 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -4,11 +4,11 @@ // CHECK: @_ZN6pr96081xE = global [3 x i8]* null, align 8, !dbg [[X:![0-9]+]] // CHECK: define void @_ZN7pr147634funcENS_3fooE -// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata ![[EXPR:[0-9]+]]) +// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata !DIExpression()) // !llvm.dbg.cu pulls in globals and their types first. // CHECK-NOT: !DIGlobalVariable(name: "c" -// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:!.*]]) +// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:!.*]], expr: !DIExpression()) // CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE" // CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]] // CHECK: [[INCARRAYPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[INCARRAY:![0-9]+]] @@ -21,7 +21,6 @@ // CHECK: ![[INCTYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "incomplete" // CHECK-SAME: DIFlagFwdDecl -// CHECK: ![[EXPR]] = !DIExpression() template<typename T> struct Identity { typedef T Type; diff --git a/test/CodeGenCXX/default_calling_conv.cpp b/test/CodeGenCXX/default_calling_conv.cpp index 95c214a223d4..b5b0f47ceb98 100644 --- a/test/CodeGenCXX/default_calling_conv.cpp +++ b/test/CodeGenCXX/default_calling_conv.cpp @@ -3,13 +3,23 @@ // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL // RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL // CDECL: define void @_Z5test1v // FASTCALL: define x86_fastcallcc void @_Z5test1v // STDCALL: define x86_stdcallcc void @_Z5test1v // VECTORCALL: define x86_vectorcallcc void @_Z5test1v +// REGCALL: define x86_regcallcc void @_Z17__regcall3__test1v void test1() {} +// fastcall, stdcall, vectorcall and regcall do not support variadic functions. +// CDECL: define void @_Z12testVariadicz +// FASTCALL: define void @_Z12testVariadicz +// STDCALL: define void @_Z12testVariadicz +// VECTORCALL: define void @_Z12testVariadicz +// REGCALL: define void @_Z12testVariadicz +void testVariadic(...){} + // ALL: define void @_Z5test2v void __attribute__((cdecl)) test2() {} @@ -22,6 +32,9 @@ void __attribute__((stdcall)) test4() {} // ALL: define x86_vectorcallcc void @_Z5test5v void __attribute__((vectorcall)) test5() {} +// ALL: define x86_regcallcc void @_Z17__regcall3__test6v +void __attribute__((regcall)) test6() {} + // ALL: define linkonce_odr void @_ZN1A11test_memberEv class A { public: @@ -32,3 +45,8 @@ void test() { A a; a.test_member(); } + +// ALL: define i32 @main +int main() { + return 1; +} diff --git a/test/CodeGenCXX/dllexport-vtable-thunks.cpp b/test/CodeGenCXX/dllexport-vtable-thunks.cpp new file mode 100644 index 000000000000..81811ace2ee6 --- /dev/null +++ b/test/CodeGenCXX/dllexport-vtable-thunks.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -fdeclspec -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-windows-itanium -fdeclspec -emit-llvm -o - %s | FileCheck %s + +struct __declspec(dllexport) A { + virtual void m(); +}; +struct __declspec(dllexport) B { + virtual void m(); +}; +struct __declspec(dllexport) C : A, B { + virtual void m(); +}; +void C::m() {} +// CHECK: define dllexport void @_ZThn8_N1C1mEv + +struct Base { + virtual void m(); +}; +struct __declspec(dllexport) Derived : virtual Base { + virtual void m(); +}; +void Derived::m() {} +// CHECK: define dllexport void @_ZTv0_n24_N7Derived1mEv diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index bdef2eb06e69..a446147b6cdc 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -102,15 +102,9 @@ inline int __declspec(dllexport) inlineStaticLocalsFunc() { // Declarations are not exported. -// dllexport implies a definition. -// MSC-NOT: @"\01??$VarTmplDef@UExplicitInst_Exported@@@@3HA" -// GNU-NOT: @_Z10VarTmplDefI21ExplicitInst_ExportedE -template<typename T> __declspec(dllexport) int VarTmplDef; -INSTVAR(VarTmplDef<ExplicitInst_Exported>) - // MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external global // GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external global -template<typename T> __declspec(dllexport) int VarTmplImplicitDef; +template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef; USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>) // Export definition. @@ -826,11 +820,26 @@ struct __declspec(dllexport) B { // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ" } -// dllexport trumps dllexport on an explicit instantiation. +// dllexport trumps dllimport on an explicit instantiation. template <typename T> struct ExplicitInstantiationTwoAttributes { void f() {} }; template struct __declspec(dllexport) __declspec(dllimport) ExplicitInstantiationTwoAttributes<int>; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ" +namespace pr34849 { +// Specializations of exported class template member functions get exported. +template <typename> struct __declspec(dllexport) ExportedClassTemplate { void foo(); }; +template<> void ExportedClassTemplate<int>::foo() {} +template struct ExportedClassTemplate<int>; +// M32-DAG: define dllexport x86_thiscallcc void @"\01?foo@?$ExportedClassTemplate@H@pr34849@@QAEXXZ" + +// Specializations of exported class member template functions do not get exported. +struct __declspec(dllexport) ExportedClass { template <typename> void bar() ; }; +template<> void ExportedClass::bar<int>() {} +// M32-DAG: define x86_thiscallcc void @"\01??$bar@H@ExportedClass@pr34849@@QAEXXZ" +template <typename> struct __declspec(dllexport) ExportedClassTemplate2 { template <typename> void baz(); }; +template<> template<> void ExportedClassTemplate2<int>::baz<int>() {} +// M32-DAG: define x86_thiscallcc void @"\01??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ" +} //===----------------------------------------------------------------------===// // Classes with template base classes diff --git a/test/CodeGenCXX/dllimport-dtor-thunks.cpp b/test/CodeGenCXX/dllimport-dtor-thunks.cpp new file mode 100644 index 000000000000..b381fff450da --- /dev/null +++ b/test/CodeGenCXX/dllimport-dtor-thunks.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -mconstructor-aliases %s -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s + +// FIXME: We should really consider removing -mconstructor-aliases for MS C++ +// ABI. The risk of bugs introducing ABI incompatibility under +// -mno-constructor-aliases is too high. + +// PR32990 + +// Introduces the virtual destructor. We should use the base destructor +// directly, no thunk needed. +struct __declspec(dllimport) ImportIntroVDtor { + virtual ~ImportIntroVDtor() {} +}; + +struct BaseClass { + virtual ~BaseClass() {} +}; + +// Non-virtually inherits from a non-dllimport base class. We should again call +// the derived base constructor directly. No need for the complete (aka vbase) +// destructor. +struct __declspec(dllimport) ImportOverrideVDtor : public BaseClass { + virtual ~ImportOverrideVDtor() {} +}; + +// Virtually inherits from a non-dllimport base class. This time we need to call +// the complete destructor and emit it inline. It's not exported from the DLL, +// and it must be emitted. +struct __declspec(dllimport) ImportVBaseOverrideVDtor + : public virtual BaseClass { + virtual ~ImportVBaseOverrideVDtor() {} +}; + +extern "C" void testit() { + ImportIntroVDtor t1; + ImportOverrideVDtor t2; + ImportVBaseOverrideVDtor t3; +} + +// The destructors are called in reverse order of construction. Only the third +// needs the complete destructor (_D). +// CHECK-LABEL: define void @testit() +// CHECK: call void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ"(%struct.ImportVBaseOverrideVDtor* %{{.*}}) +// CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}}) +// CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}}) + +// CHECK-LABEL: define linkonce_odr void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" +// CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ" +// CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ" diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp index 19d9e1dfe7b6..ff7868382d8c 100644 --- a/test/CodeGenCXX/dllimport-members.cpp +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -836,7 +836,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<ImplicitInst_Imported>) // Import explicit instantiation declaration of an imported member variable // template. -// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32 +// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1 // GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32 extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>; USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>) @@ -861,7 +861,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>) // Import explicit instantiation declaration of a non-imported member variable // template. -// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32 +// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1 // GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32 extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>; USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>) diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 372a96ba2efe..14558aec39a4 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -579,7 +579,7 @@ USE(inlineFuncTmpl<ExplicitDecl_Imported>) // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() // GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv() // GNU-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() -// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"() +// MO1-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() // GO1-DAG: define available_externally dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv() // GO1-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() @@ -609,6 +609,15 @@ USE(funcTmpl<ExplicitSpec_Imported>) template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} USE(funcTmpl<ExplicitSpec_InlineDef_Imported>) +#ifdef MSABI +namespace pr35435 { +struct X; +template <typename T> struct __declspec(dllimport) S { + void foo(T *t) { t->problem(); } +}; +template void S<X>::foo(X*); // Cannot be instantiated because X is incomplete; dllimport means it's treated as an instantiation decl. +} +#endif //===----------------------------------------------------------------------===// diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index db0576a1baeb..dfbe48c37239 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -461,12 +461,12 @@ class DerivedException: public BaseException { int foo() { throw DerivedException(); - // The alignment passed to memset is 8, not 16, on Darwin. + // The alignment passed to memset is 16 on Darwin. // CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i64 16) // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to %"class.test17::DerivedException"* // CHECK-NEXT: [[T2:%.*]] = bitcast %"class.test17::DerivedException"* [[T1]] to i8* - // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 8, i1 false) + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 16, i1 false) } } diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index 4f7eacd66720..fa2d834c1e38 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -76,6 +76,27 @@ extern "C" void use_seh() { // CHECK: [[cont]] // CHECK: br label %[[ret]] +extern "C" void nested_finally() { + __try { + might_throw(); + } __finally { + __try { + might_throw(); + } __finally { + } + } +} + +// CHECK-LABEL: define void @nested_finally() #{{[0-9]+}} +// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: invoke void @might_throw() +// CHECK: call void @"\01?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}}) + +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested_finally@@" +// CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: invoke void @might_throw() +// CHECK: call void @"\01?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}}) + void use_seh_in_lambda() { ([]() { __try { diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 85857fb6fb8c..ad20abde8f11 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -170,3 +170,22 @@ void use() { f<int>(); } } + +namespace DefaultedMembers { + struct B { B(); B(const B&); ~B(); }; + template<typename T> struct A : B { + A() = default; + ~A() = default; + }; + extern template struct A<int>; + + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2Ev + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiED2Ev + A<int> ai; + + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2ERKS1_ + A<int> ai2(ai); + + // CHECK-NOT: @_ZN16DefaultedMembers1AIcE + template struct A<char>; +} diff --git a/test/CodeGenCXX/extern-section-attribute.cpp b/test/CodeGenCXX/extern-section-attribute.cpp new file mode 100644 index 000000000000..fa0227e6fe1a --- /dev/null +++ b/test/CodeGenCXX/extern-section-attribute.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu | FileCheck %s + +extern int aa __attribute__((section(".sdata"))); +// CHECK-DAG: @aa = external global i32, section ".sdata", align 4 + +extern int bb __attribute__((section(".sdata"))) = 1; +// CHECK-DAG: @bb = global i32 1, section ".sdata", align 4 + +int foo() { + return aa + bb; +} diff --git a/test/CodeGenCXX/finegrain-bitfield-access.cpp b/test/CodeGenCXX/finegrain-bitfield-access.cpp new file mode 100644 index 000000000000..2973f9f73c4e --- /dev/null +++ b/test/CodeGenCXX/finegrain-bitfield-access.cpp @@ -0,0 +1,162 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ +// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \ +// RUN: -emit-llvm -fsanitize=address -o - %s | FileCheck %s --check-prefix=SANITIZE +// Check -fsplit-bitfields will be ignored since sanitizer is enabled. + +struct S1 { + unsigned f1:2; + unsigned f2:6; + unsigned f3:8; + unsigned f4:4; + unsigned f5:8; +}; + +S1 a1; +unsigned read8_1() { + // CHECK-LABEL: @_Z7read8_1v + // CHECK: %bf.load = load i8, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 + // CHECK-NEXT: %bf.cast = zext i8 %bf.load to i32 + // CHECK-NEXT: ret i32 %bf.cast + // SANITIZE-LABEL: @_Z7read8_1v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE: %bf.lshr = lshr i32 %bf.load, 8 + // SANITIZE: %bf.clear = and i32 %bf.lshr, 255 + // SANITIZE: ret i32 %bf.clear + return a1.f3; +} +void write8_1() { + // CHECK-LABEL: @_Z8write8_1v + // CHECK: store i8 3, i8* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 1), align 1 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z8write8_1v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -65281 + // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 768 + // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: ret void + a1.f3 = 3; +} + +unsigned read8_2() { + // CHECK-LABEL: @_Z7read8_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: %bf.lshr = lshr i16 %bf.load, 4 + // CHECK-NEXT: %bf.clear = and i16 %bf.lshr, 255 + // CHECK-NEXT: %bf.cast = zext i16 %bf.clear to i32 + // CHECK-NEXT: ret i32 %bf.cast + // SANITIZE-LABEL: @_Z7read8_2v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.lshr = lshr i32 %bf.load, 20 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.lshr, 255 + // SANITIZE-NEXT: ret i32 %bf.clear + return a1.f5; +} +void write8_2() { + // CHECK-LABEL: @_Z8write8_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: %bf.clear = and i16 %bf.load, -4081 + // CHECK-NEXT: %bf.set = or i16 %bf.clear, 48 + // CHECK-NEXT: store i16 %bf.set, i16* getelementptr inbounds (%struct.S1, %struct.S1* @a1, i32 0, i32 2), align 2 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z8write8_2v + // SANITIZE: %bf.load = load i32, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: %bf.clear = and i32 %bf.load, -267386881 + // SANITIZE-NEXT: %bf.set = or i32 %bf.clear, 3145728 + // SANITIZE-NEXT: store i32 %bf.set, i32* getelementptr inbounds {{.*}}, align 4 + // SANITIZE-NEXT: ret void + a1.f5 = 3; +} + +struct S2 { + unsigned long f1:16; + unsigned long f2:16; + unsigned long f3:6; +}; + +S2 a2; +unsigned read16_1() { + // CHECK-LABEL: @_Z8read16_1v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 + // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read16_1v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 65535 + // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 + // SANITIZE-NEXT: ret i32 %conv + return a2.f1; +} +unsigned read16_2() { + // CHECK-LABEL: @_Z8read16_2v + // CHECK: %bf.load = load i16, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 + // CHECK-NEXT: %bf.cast = zext i16 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read16_2v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 16 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.lshr, 65535 + // SANITIZE-NEXT: %conv = trunc i64 %bf.clear to i32 + // SANITIZE-NEXT: ret i32 %conv + return a2.f2; +} + +void write16_1() { + // CHECK-LABEL: @_Z9write16_1v + // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 0), align 8 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write16_1v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -65536 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 5 + // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a2.f1 = 5; +} +void write16_2() { + // CHECK-LABEL: @_Z9write16_2v + // CHECK: store i16 5, i16* getelementptr inbounds (%struct.S2, %struct.S2* @a2, i32 0, i32 1), align 2 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write16_2v + // SANITIZE: %bf.load = load i64, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, -4294901761 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 327680 + // SANITIZE-NEXT: store i64 %bf.set, i64* bitcast {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a2.f2 = 5; +} + +struct S3 { + unsigned long f1:14; + unsigned long f2:18; + unsigned long f3:32; +}; + +S3 a3; +unsigned read32_1() { + // CHECK-LABEL: @_Z8read32_1v + // CHECK: %bf.load = load i32, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 + // CHECK-NEXT: %bf.cast = zext i32 %bf.load to i64 + // CHECK-NEXT: %conv = trunc i64 %bf.cast to i32 + // CHECK-NEXT: ret i32 %conv + // SANITIZE-LABEL: @_Z8read32_1v + // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: %bf.lshr = lshr i64 %bf.load, 32 + // SANITIZE-NEXT: %conv = trunc i64 %bf.lshr to i32 + // SANITIZE-NEXT: ret i32 %conv + return a3.f3; +} +void write32_1() { + // CHECK-LABEL: @_Z9write32_1v + // CHECK: store i32 5, i32* getelementptr inbounds (%struct.S3, %struct.S3* @a3, i32 0, i32 1), align 4 + // CHECK-NEXT: ret void + // SANITIZE-LABEL: @_Z9write32_1v + // SANITIZE: %bf.load = load i64, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: %bf.clear = and i64 %bf.load, 4294967295 + // SANITIZE-NEXT: %bf.set = or i64 %bf.clear, 21474836480 + // SANITIZE-NEXT: store i64 %bf.set, i64* getelementptr inbounds {{.*}}, align 8 + // SANITIZE-NEXT: ret void + a3.f3 = 5; +} diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp new file mode 100644 index 000000000000..87ef139f8634 --- /dev/null +++ b/test/CodeGenCXX/float16-declarations.cpp @@ -0,0 +1,149 @@ +// RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 +// RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86 + +/* Various contexts where type _Float16 can appear. */ + + +/* Namespace */ + +namespace { + _Float16 f1n; +// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global half 0xH0000, align 2 + + _Float16 f2n = 33.f16; +// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global half 0xH5020, align 2 + + _Float16 arr1n[10]; +// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16 + + _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2 + + const volatile _Float16 func1n(const _Float16 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + + +/* File */ + +_Float16 f1f; +// CHECK-AARCH64-DAG: @f1f = global half 0xH0000, align 2 +// CHECK-X86-DAG: @f1f = global half 0xH0000, align 2 + +_Float16 f2f = 32.4; +// CHECK-DAG: @f2f = global half 0xH500D, align 2 + +_Float16 arr1f[10]; +// CHECK-AARCH64-DAG: @arr1f = global [10 x half] zeroinitializer, align 2 +// CHECK-X86-DAG: @arr1f = global [10 x half] zeroinitializer, align 16 + +_Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; +// CHECK-DAG: @arr2f = global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 + +_Float16 func1f(_Float16 arg); + + +/* Class */ + +class C1 { + _Float16 f1c; + + static const _Float16 f2c; +// CHECK-DAG: @_ZN2C13f2cE = external constant half, align 2 + + volatile _Float16 f3c; + +public: + C1(_Float16 arg) : f1c(arg), f3c(arg) { } +// Check that we mangle _Float16 to DF16_ +// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}}) + + _Float16 func1c(_Float16 arg ) { + return f1c + arg; + } +// CHECK-DAG: define linkonce_odr half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}}) + + static _Float16 func2c(_Float16 arg) { + return arg * C1::f2c; + } +// CHECK-DAG: define linkonce_odr half @_ZN2C16func2cEDF16_(half{{.*}}) +}; + +/* Template */ + +template <class C> C func1t(C arg) { + return arg * 2.f16; +} +// CHECK-DAG: define linkonce_odr half @_Z6func1tIDF16_ET_S0_(half{{.*}}) + +template <class C> struct S1 { + C mem1; +}; + +template <> struct S1<_Float16> { + _Float16 mem2; +}; + + +/* Local */ + +extern int printf (const char *__restrict __format, ...); + +int main(void) { + _Float16 f1l = 1e3f16; +// CHECK-DAG: store half 0xH63D0, half* %{{.*}}, align 2 + + _Float16 f2l = -0.f16; +// CHECK-DAG: store half 0xH8000, half* %{{.*}}, align 2 + + _Float16 f3l = 1.000976562; +// CHECK-DAG: store half 0xH3C01, half* %{{.*}}, align 2 + + C1 c1(f1l); +// CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2 +// 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: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8* +// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[S1]], i8* bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false) + + _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; + + auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); +// CHECK-DAG: store half 0xHBC00, half* %{{.*}}, align 2 +// CHECK-DAG: store half* %{{.*}}, half** %{{.*}}, align 8 + + _Float16 f8l = f4l++; +// CHECK-DAG: %{{.*}} = load half, half* %{{.*}}, align 2 +// CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd half {{.*}}, 0xH3C00 +// 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 + + float cvtf = f2n; +//CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float +//CHECK-DAG: store float [[H2F]], float* %{{.*}}, align 4 + + double cvtd = f2n; +//CHECK-DAG: [[H2D:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to double +//CHECK-DAG: store double [[H2D]], double* %{{.*}}, align 8 + + + long double cvtld = f2n; +//CHECK-AARCh64-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to fp128 +//CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %{{.*}}, align 16 +//CHECK-X86-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80 +//CHECK-X86-DAG: store x86_fp80 [[H2LD]], x86_fp80* %{{.*}}, align 16 + + _Float16 f2h = 42.0f; +//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2 + _Float16 d2h = 42.0; +//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2 + _Float16 ld2h = 42.0l; +//CHECK-DAG:store half 0xH5140, half* %{{.*}}, align 2 +} diff --git a/test/CodeGenCXX/fp16-mangle.cpp b/test/CodeGenCXX/fp16-mangle.cpp index bd5a3194112c..5827fd549dc2 100644 --- a/test/CodeGenCXX/fp16-mangle.cpp +++ b/test/CodeGenCXX/fp16-mangle.cpp @@ -4,9 +4,9 @@ template <typename T, typename U> struct S { static int i; }; template <> int S<__fp16, __fp16>::i = 3; -// CHECK-LABEL: define void @_Z1fPDh(i16* %x) +// CHECK-LABEL: define void @_Z1fPDh(half* %x) void f (__fp16 *x) { } -// CHECK-LABEL: define void @_Z1gPDhS_(i16* %x, i16* %y) +// CHECK-LABEL: define void @_Z1gPDhS_(half* %x, half* %y) void g (__fp16 *x, __fp16 *y) { } diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp index 66ef459bd80b..a98f5601d3bc 100644 --- a/test/CodeGenCXX/inline-dllexport-member.cpp +++ b/test/CodeGenCXX/inline-dllexport-member.cpp @@ -7,7 +7,7 @@ struct __declspec(dllexport) s { static const unsigned int ui = 0; }; -// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]]) +// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]], expr: !DIExpression()) // CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]], // CHECK: ![[SCOPE]] = distinct !DICompileUnit( diff --git a/test/CodeGenCXX/instrument-functions.cpp b/test/CodeGenCXX/instrument-functions.cpp index 587b6389c9a9..45ae48235a9d 100644 --- a/test/CodeGenCXX/instrument-functions.cpp +++ b/test/CodeGenCXX/instrument-functions.cpp @@ -1,22 +1,26 @@ -// RUN: %clang_cc1 -S -emit-llvm -triple %itanium_abi_triple -o - %s -finstrument-functions | FileCheck %s +// RUN: %clang_cc1 -S -emit-llvm -triple %itanium_abi_triple -o - %s -finstrument-functions -disable-llvm-passes | FileCheck %s -// CHECK: @_Z5test1i int test1(int x) { -// CHECK: __cyg_profile_func_enter -// CHECK: __cyg_profile_func_exit +// CHECK: @_Z5test1i(i32 {{.*}}%x) #[[ATTR1:[0-9]+]] // CHECK: ret return x; } -// CHECK: @_Z5test2i int test2(int) __attribute__((no_instrument_function)); int test2(int x) { -// CHECK-NOT: __cyg_profile_func_enter -// CHECK-NOT: __cyg_profile_func_exit +// CHECK: @_Z5test2i(i32 {{.*}}%x) #[[ATTR2:[0-9]+]] // CHECK: ret return x; } +// CHECK: attributes #[[ATTR1]] = +// CHECK-SAME: "instrument-function-entry"="__cyg_profile_func_enter" +// CHECK-SAME: "instrument-function-exit"="__cyg_profile_func_exit" + +// CHECK: attributes #[[ATTR2]] = +// CHECK-NOT: "instrument-function-entry" + + // This test case previously crashed code generation. It exists solely // to test -finstrument-function does not crash codegen for this trivial // case. diff --git a/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/test/CodeGenCXX/invariant.group-for-vptrs.cpp index 4e5d9b49d985..45671e5a2c2a 100644 --- a/test/CodeGenCXX/invariant.group-for-vptrs.cpp +++ b/test/CodeGenCXX/invariant.group-for-vptrs.cpp @@ -56,7 +56,7 @@ void testInternallyVisible(bool p) { // Checking D::D() // CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev( -// CHECK: = call i8* @llvm.invariant.group.barrier(i8* +// CHECK: = call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK: call void @_ZN1AC2Ev(%struct.A* // CHECK: store {{.*}} !invariant.group ![[MD]] diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index ee7594b2fdd2..6c4640269403 100644 --- a/test/CodeGenCXX/mangle-exprs.cpp +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -314,6 +314,19 @@ namespace test7 { template<class T> decltype(F{{1,2}},T()) fF1(T t) {} template<class T> decltype(F({1,2}),T()) fF2(T t) {} + template<class T> decltype(T{}) fT1(T t) {} + template<class T> decltype(T()) fT2(T t) {} + template<class T> decltype(T{1}) fT3(T t) {} + template<class T> decltype(T(1)) fT4(T t) {} + template<class T> decltype(T{1,2}) fT5(T t) {} + template<class T> decltype(T(1,2)) fT6(T t) {} + template<class T> decltype(T{{}}) fT7(T t) {} + template<class T> decltype(T({})) fT8(T t) {} + template<class T> decltype(T{{1}}) fT9(T t) {} + template<class T> decltype(T({1})) fTA(T t) {} + template<class T> decltype(T{{1,2}}) fTB(T t) {} + template<class T> decltype(T({1,2})) fTC(T t) {} + int main() { fA1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fA1IiEEDTcmtlNS_1AELi1ELi2EEcvT__EES2_ fA2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fA2IiEEDTcmcvNS_1AEilLi1ELi2EEcvT__EES2_ @@ -327,6 +340,18 @@ namespace test7 { fE2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fE2IiEEDTcmcvNS_1EEilLi1ELi2EEcvT__EES2_ fF1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fF1IiEEDTcmtlNS_1FEilLi1ELi2EEEcvT__EES2_ fF2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fF2IiEEDTcmcvNS_1FEilLi1ELi2EEcvT__EES2_ + fT1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fT1IiEEDTtlT_EES1_( + fT2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fT2IiEEDTcvT__EES1_( + fT3(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fT3IiEEDTtlT_Li1EEES1_( + fT4(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fT4IiEEDTcvT_Li1EES1_( + fT5(b); // CHECK-LABEL: define {{.*}} @_ZN5test73fT5INS_1BEEEDTtlT_Li1ELi2EEES2_( + fT6(b); // CHECK-LABEL: define {{.*}} @_ZN5test73fT6INS_1BEEEDTcvT__Li1ELi2EEES2_( + fT7(A{}); // CHECK-LABEL: define {{.*}} @_ZN5test73fT7INS_1AEEEDTtlT_ilEEES2_( + fT8(A{}); // CHECK-LABEL: define {{.*}} @_ZN5test73fT8INS_1AEEEDTcvT_ilEES2_( + fT9(A{}); // CHECK-LABEL: define {{.*}} @_ZN5test73fT9INS_1AEEEDTtlT_ilLi1EEEES2_( + fTA(A{}); // CHECK-LABEL: define {{.*}} @_ZN5test73fTAINS_1AEEEDTcvT_ilLi1EEES2_( + fTB<C>(b); // CHECK-LABEL: define {{.*}} @_ZN5test73fTBINS_1CEEEDTtlT_ilLi1ELi2EEEES2_( + fTC<C>(b); // CHECK-LABEL: define {{.*}} @_ZN5test73fTCINS_1CEEEDTcvT_ilLi1ELi2EEES2_( } } @@ -341,3 +366,10 @@ namespace test8 { // CHECK-LABEL: define weak_odr i32 @_ZNK5test81XIiE3barIiEEDTcl3fooIT_EEEv template int X<int>::bar<int>() const; } + +namespace designated_init { + struct A { struct B { int b[5][5]; } a; }; + // CHECK-LABEL: define {{.*}} @_ZN15designated_init1fINS_1AEEEvDTtlT_di1adi1bdxLi3EdXLi1ELi4ELi9EEE( + template<typename T> void f(decltype(T{.a.b[3][1 ... 4] = 9}) x) {} + void use_f(A a) { f<A>(a); } +} diff --git a/test/CodeGenCXX/mangle-fail.cpp b/test/CodeGenCXX/mangle-fail.cpp index 02548964efc9..b588d57749fa 100644 --- a/test/CodeGenCXX/mangle-fail.cpp +++ b/test/CodeGenCXX/mangle-fail.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 -emit-llvm-only -x c++ -std=c++11 -triple %itanium_abi_triple -verify %s -DN=1 // RUN: %clang_cc1 -emit-llvm-only -x c++ -std=c++11 -triple %itanium_abi_triple -verify %s -DN=2 -// RUN: %clang_cc1 -emit-llvm-only -x c++ -std=c++11 -triple %itanium_abi_triple -verify %s -DN=3 struct A { int a; }; @@ -14,11 +13,6 @@ template void test<int>(int (&)[sizeof(int)]); template<class T> void test(int (&)[sizeof((A){}, T())]) {} // expected-error {{cannot yet mangle}} template void test<int>(int (&)[sizeof(A)]); -#elif N == 3 -// DesignatedInitExpr -template<class T> void test(int (&)[sizeof(A{.a = 10}, T())]) {} // expected-error {{cannot yet mangle}} -template void test<int>(int (&)[sizeof(A)]); - // FIXME: There are several more cases we can't yet mangle. #else diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp index 15987ebe46bd..d49ed4b2a5e1 100644 --- a/test/CodeGenCXX/mangle-lambdas.cpp +++ b/test/CodeGenCXX/mangle-lambdas.cpp @@ -26,6 +26,24 @@ void call_inline_func() { inline_func(17); } +// CHECK-LABEL: define linkonce_odr i32* @_ZNK10inline_varMUlvE_clEv( +// CHECK: @_ZZNK10inline_varMUlvE_clEvE1n +inline auto inline_var = [] { + static int n = 5; + return &n; +}; + +int *use_inline_var = inline_var(); + +// CHECK-LABEL: define linkonce_odr i32* @_ZNK12var_templateIiEMUlvE_clEv( +// CHECK: @_ZZNK12var_templateIiEMUlvE_clEvE1n +template<typename T> auto var_template = [] { + static int n = 9; + return &n; +}; + +int *use_var_template = var_template<int>(); + struct S { void f(int = []{return 1;}() + []{return 2;}(), @@ -118,7 +136,7 @@ T StaticMembers<T>::z = accept_lambda([]{return 4;}); template<typename T> int (*StaticMembers<T>::f)() = []{return 5;}; -// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK-LABEL: define internal void @__cxx_global_var_init // CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv // CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv // CHECK-NEXT: add nsw @@ -128,23 +146,23 @@ int (*StaticMembers<T>::f)() = []{return 5;}; // CHECK: ret i32 2 template float StaticMembers<float>::x; -// CHECK-LABEL: define internal void @__cxx_global_var_init.1() +// CHECK-LABEL: define internal void @__cxx_global_var_init // CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv // CHECK-LABEL: define linkonce_odr i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv // CHECK: ret i32 3 template float StaticMembers<float>::y; -// CHECK-LABEL: define internal void @__cxx_global_var_init.2() +// CHECK-LABEL: define internal void @__cxx_global_var_init // CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_ // CHECK: declare i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_() template float StaticMembers<float>::z; -// CHECK-LABEL: define internal void @__cxx_global_var_init.3() +// CHECK-LABEL: define internal void @__cxx_global_var_init // CHECK: call {{.*}} @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv // CHECK-LABEL: define linkonce_odr i32 ()* @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv template int (*StaticMembers<float>::f)(); -// CHECK-LABEL: define internal void @__cxx_global_var_init.4 +// CHECK-LABEL: define internal void @__cxx_global_var_init // CHECK: call i32 @"_ZNK13StaticMembersIdE3$_2clEv" // CHECK-LABEL: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv" // CHECK: ret i32 42 diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 819b0d9c9d0d..b22c04698ea2 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -160,6 +160,8 @@ struct { } a; decltype(a) fun(decltype(a) x, decltype(a)) { return x; } // CHECK-DAG: @"\01?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z" +void use_fun() { fun(a, a); } + } inline int define_lambda() { @@ -280,7 +282,7 @@ void g() { namespace PR18204 { template <typename T> -int f(T *); +int f(T *) { return 0; } static union { int n = f(this); }; @@ -346,4 +348,5 @@ int call_it = (A::default_args(), 1); enum { enumerator }; void f(decltype(enumerator)) {} -// CHECK-DAG: define void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"( +// CHECK-DAG: define internal void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"( +void use_f() { f(enumerator); } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 91fe6aeef298..919f8afb1607 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -893,7 +893,8 @@ namespace test39 { struct {} a; } *foo; template<typename T> void func(T) {} - void test(foo x) { + void test() { + foo x; func(x->a); } } diff --git a/test/CodeGenCXX/member-expr-references-variable.cpp b/test/CodeGenCXX/member-expr-references-variable.cpp new file mode 100644 index 000000000000..8c1dded800f6 --- /dev/null +++ b/test/CodeGenCXX/member-expr-references-variable.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct Agg { const char * x; const char * y; constexpr Agg() : x(0), y(0) {} }; + +struct Struct { + constexpr static const char *name = "foo"; + + constexpr static __complex float complexValue = 42.0; + + static constexpr const Agg &agg = Agg(); + + Struct(); + Struct(int x); +}; + +void use(int n, const char *c); + +Struct *getPtr(); + +// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1 + +void scalarStaticVariableInMemberExpr(Struct *ptr, Struct &ref) { + use(1, Struct::name); +// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + Struct s; + use(2, s.name); +// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(3, ptr->name); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(4, ref.name); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(5, Struct(2).name); +// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2) +// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) + use(6, getPtr()->name); +// CHECK: call %struct.Struct* @_Z6getPtrv() +// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0)) +} + +void use(int n, __complex float v); + +void complexStaticVariableInMemberExpr(Struct *ptr, Struct &ref) { + use(1, Struct::complexValue); +// CHECK: store float 4.200000e+01, float* %[[coerce0:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce0]].{{.*}}, align 4 +// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>* +// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4 +// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]]) + Struct s; + use(2, s.complexValue); +// CHECK: store float 4.200000e+01, float* %[[coerce1:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce1]].{{.*}}, align 4 +// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>* +// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4 +// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]]) + use(3, ptr->complexValue); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: store float 4.200000e+01, float* %[[coerce2:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce2]].{{.*}}, align 4 +// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>* +// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4 +// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]]) + use(4, ref.complexValue); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: store float 4.200000e+01, float* %[[coerce3:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce3]].{{.*}}, align 4 +// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>* +// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4 +// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]]) + use(5, Struct(2).complexValue); +// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2) +// CHECK: store float 4.200000e+01, float* %[[coerce4:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce4]].{{.*}}, align 4 +// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>* +// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4 +// CHECK: call void @_Z3useiCf(i32 5, <2 x float> %[[vector4]]) + use(6, getPtr()->complexValue); +// CHECK: call %struct.Struct* @_Z6getPtrv() +// CHECK: store float 4.200000e+01, float* %[[coerce5:.*]].{{.*}}, align 4 +// CHECK: store float 0.000000e+00, float* %[[coerce5]].{{.*}}, align 4 +// CHECK: %[[cast5:.*]] = bitcast { float, float }* %[[coerce5]] to <2 x float>* +// CHECK: %[[vector5:.*]] = load <2 x float>, <2 x float>* %[[cast5]], align 4 +// CHECK: call void @_Z3useiCf(i32 6, <2 x float> %[[vector5]]) +} + +void aggregateRefInMemberExpr(Struct *ptr, Struct &ref) { + use(1, Struct::agg.x); +// CHECK: %[[value0:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8 +// CHECK: call void @_Z3useiPKc(i32 1, i8* %[[value0]]) + Struct s; + use(2, s.agg.x); +// CHECK: %[[value1:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8 +// CHECK: call void @_Z3useiPKc(i32 2, i8* %[[value1]]) + use(3, ptr->agg.x); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: %[[value2:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8 +// CHECK: call void @_Z3useiPKc(i32 3, i8* %[[value2]]) + use(4, ref.agg.x); +// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8 +// CHECK: %[[value3:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8 +// CHECK: call void @_Z3useiPKc(i32 4, i8* %[[value3]]) +} diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index f3e43079c3eb..8d75ed4d9d69 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -78,7 +78,7 @@ T* test6(B* x) { return dynamic_cast<T*>(x); } // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* nonnull [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi %struct.T* @@ -117,7 +117,7 @@ void* test9(B* x) { return dynamic_cast<void*>(x); } // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* nonnull [[ADJ]]) // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi i8* // CHECK-NEXT: ret i8* [[RET]] diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp index f9db2680e336..5bed69ff117f 100644 --- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp @@ -19,7 +19,7 @@ struct ChildOverride : Left, Right { extern "C" void foo(void *); void call_left_no_override(ChildNoOverride *child) { -// CHECK: define void @"\01?call_left_no_override +// CHECK-LABEL: define void @"\01?call_left_no_override // CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride child->left(); @@ -34,7 +34,8 @@ void call_left_no_override(ChildNoOverride *child) { } void ChildOverride::left() { -// CHECK: define x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ"(%struct.ChildOverride* %[[THIS:.*]]) +// CHECK-LABEL: define x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ" +// CHECK-SAME: (%struct.ChildOverride* %[[THIS:.*]]) // // No need to adjust 'this' as the ChildOverride's layout begins with Left. // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4 @@ -48,7 +49,7 @@ void ChildOverride::left() { } void call_left_override(ChildOverride *child) { -// CHECK: define void @"\01?call_left_override +// CHECK-LABEL: define void @"\01?call_left_override // CHECK: %[[CHILD:.*]] = load %struct.ChildOverride child->left(); @@ -62,7 +63,7 @@ void call_left_override(ChildOverride *child) { } void call_right_no_override(ChildNoOverride *child) { -// CHECK: define void @"\01?call_right_no_override +// CHECK-LABEL: define void @"\01?call_right_no_override // CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride child->right(); @@ -82,25 +83,27 @@ void call_right_no_override(ChildNoOverride *child) { } void ChildOverride::right() { -// CHECK: define x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8* +// CHECK-LABEL: define x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8* // // ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we // need to adjust 'this' before use. // // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4 -// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -4 -// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.ChildOverride* -// CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4 +// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride* +// CHECK: store %struct.ChildOverride* %[[THIS_INIT]], %struct.ChildOverride** %[[THIS_ADDR]], align 4 +// CHECK: %[[THIS_RELOAD:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]] +// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS_RELOAD]] to i8* +// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 -4 +// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJUSTED]] to %struct.ChildOverride* foo(this); -// CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]] // CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8* // CHECK: call void @foo(i8* %[[THIS_PARAM]]) // CHECK: ret } void call_right_override(ChildOverride *child) { -// CHECK: define void @"\01?call_right_override +// CHECK-LABEL: define void @"\01?call_right_override // CHECK: %[[CHILD:.*]] = load %struct.ChildOverride child->right(); @@ -127,15 +130,17 @@ struct GrandchildOverride : ChildOverride { }; void GrandchildOverride::right() { -// CHECK: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8* +// CHECK-LABEL: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8* // // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4 -// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -4 -// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.GrandchildOverride* -// CHECK: store %struct.GrandchildOverride* %[[THIS]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4 +// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride* +// CHECK: store %struct.GrandchildOverride* %[[THIS_INIT]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4 +// CHECK: %[[THIS_RELOAD:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]] +// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS_RELOAD]] to i8* +// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 -4 +// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJUSTED]] to %struct.GrandchildOverride* foo(this); -// CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]] // CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8* // CHECK: call void @foo(i8* %[[THIS_PARAM]]) // CHECK: ret @@ -148,19 +153,19 @@ void call_grandchild_right(GrandchildOverride *obj) { void emit_ctors() { Left l; - // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ" + // CHECK-LABEL: define {{.*}} @"\01??0Left@@QAE@XZ" // CHECK-NOT: getelementptr // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Left@@6B@" to i32 (...)**) // CHECK: ret Right r; - // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ" + // CHECK-LABEL: define {{.*}} @"\01??0Right@@QAE@XZ" // CHECK-NOT: getelementptr // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Right@@6B@" to i32 (...)**) // CHECK: ret ChildOverride co; - // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ" + // CHECK-LABEL: define {{.*}} @"\01??0ChildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)*** // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] @@ -171,7 +176,7 @@ void emit_ctors() { // CHECK: ret GrandchildOverride gc; - // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ" + // CHECK-LABEL: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)*** // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp index 57a72d4e2a6c..0b84f07e1154 100644 --- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp +++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp @@ -146,7 +146,7 @@ inline S &getS() { // CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ"() {{.*}} comdat // CHECK: load i32, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51" // CHECK: and i32 {{.*}}, 1 -// CHECK: icmp ne i32 {{.*}}, 0 +// CHECK: icmp eq i32 {{.*}}, 0 // CHECK: br i1 // init: // CHECK: or i32 {{.*}}, 1 diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp index 0202586c8a62..3f53e631c964 100644 --- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp +++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp @@ -24,8 +24,8 @@ extern inline S &f() { static thread_local S s; // CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51" // CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], 1 -// CHECK-NEXT: %[[cmp:.*]] = icmp ne i32 %[[mask]], 0 -// CHECK-NEXT: br i1 %[[cmp]], label %[[init_end:.*]], label %[[init:.*]] +// CHECK-NEXT: %[[cmp:.*]] = icmp eq i32 %[[mask]], 0 +// CHECK-NEXT: br i1 %[[cmp]], label %[[init:.*]], label %[[init_end:.*]], !prof ![[unlikely_threadlocal:.*]] // // CHECK: [[init]]: // CHECK-NEXT: %[[or:.*]] = or i32 %[[guard]], 1 @@ -56,7 +56,7 @@ extern inline S &g() { // CHECK: %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4 // CHECK-NEXT: %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch // CHECK-NEXT: %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]] -// CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]] +// CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]], !prof ![[unlikely_staticlocal:.*]] // // CHECK: [[init_attempt]]: // CHECK-NEXT: call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA") @@ -95,3 +95,6 @@ int g1() { static int i = f1(); return i; } + +// CHECK-DAG: ![[unlikely_threadlocal]] = !{!"branch_weights", i32 1, i32 1023} +// CHECK-DAG: ![[unlikely_staticlocal]] = !{!"branch_weights", i32 1, i32 1048575} diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index bb73f8773ccb..2f141b2a66ec 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -24,6 +24,7 @@ struct D : virtual C { D::D() {} // Forces vftable emission. // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" +// Note that the vtordisp is applied before really adjusting to D*. // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4 diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 20ecaf431650..c9dd1dd7d8e2 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t +// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t // RUN: FileCheck %s < %t // RUN: FileCheck --check-prefix=CHECK2 %s < %t // For now, just make sure x86_64 doesn't crash. -// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t +// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t struct VBase { virtual ~VBase(); @@ -52,12 +52,14 @@ B::B() { B::~B() { // CHECK-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ" - // Adjust the this parameter: - // CHECK: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8* - // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8]], i32 -8 - // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* - // CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4 - // CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] + // Store initial this: + // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B* + // CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4 + // Reload and adjust the this parameter: + // CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] + // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8* + // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8 + // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B* // Restore the vfptr that could have been changed by a subclass. // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -97,11 +99,11 @@ B::~B() { // CHECK2: ret // CHECK2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_GB@@UAEPAXI@Z" - // CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8* + // CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4 + // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] + // CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8 // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* - // CHECK2: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4 - // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] // CHECK2: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[THIS]]) // ... // CHECK2: ret @@ -113,13 +115,17 @@ void B::foo() { // B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we // need to adjust 'this' before use. // -// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4 -// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -8 -// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* -// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4 +// Store initial this: +// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B* +// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4 +// +// Reload and adjust the this parameter: +// CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] +// CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8* +// CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8 +// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B* field = 42; -// CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 0 // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** @@ -284,11 +290,16 @@ struct D : virtual Z, B, C { D::~D() { // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}}) - // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8* - // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ARG_i8]], i32 -24 - // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"* - // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4 - // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_VAL]] + // Store initial this: + // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"* + // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4 + // + // Reload and adjust the this parameter: + // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]] + // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8* + // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24 + // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"* + // // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8* // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4 // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"* diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp index b97c432f5e02..385e9cc17b1b 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp @@ -196,7 +196,11 @@ void C::g(NonTrivial o) { } // BITCODE-LABEL: define void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca) -// BITCODE: %[[this1:[^ ]*]] = load i8*, i8** %[[thisaddr:[^ ]*]], align 4 -// BITCODE-NEXT: %[[this2:[^ ]*]] = getelementptr inbounds i8, i8* %[[this1]], i32 -4 -// BITCODE-NEXT: store i8* %[[this2]], i8** %[[thisaddr]], align 4 +// BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0 +// BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"** +// BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4 +// BITCODE: %[[this2:[^ ]*]] = bitcast %"struct.pr30293::C"* %[[this1]] to i8* +// BITCODE: %[[this3:[^ ]*]] = getelementptr inbounds i8, i8* %[[this2]], i32 -4 +// BITCODE: %[[this4:[^ ]*]] = bitcast i8* %[[this3]] to %"struct.pr30293::C"* +// BITCODE: store %"struct.pr30293::C"* %[[this4]], %"struct.pr30293::C"** @"\01?whatsthis@pr30293@@3PAUC@1@A", align 4 } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp index 2bf7da58ea9c..feba91c50556 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -201,3 +201,18 @@ D::D() {} // GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ" // GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ" } + +namespace pr34302 { +// C::f is lives in the vftable inside its virtual B subobject. In the MS ABI, +// covariant return type virtual methods extend vftables from virtual bases, +// even though that can make it impossible to implement certain diamond +// hierarchies correctly. +struct A { virtual ~A(); }; +struct B : A { virtual B *f(); }; +struct C : virtual B { C *f(); }; +C c; +// VFTABLES-LABEL: VFTable indices for 'pr34302::C' (2 entries). +// VFTABLES-NEXT: -- accessible via vbtable index 1, vfptr at offset 0 -- +// VFTABLES-NEXT: 0 | pr34302::C::~C() [scalar deleting] +// VFTABLES-NEXT: 2 | pr34302::C *pr34302::C::f() +} diff --git a/test/CodeGenCXX/microsoft-inaccessible-base.cpp b/test/CodeGenCXX/microsoft-inaccessible-base.cpp new file mode 100644 index 000000000000..2c0d124eb01e --- /dev/null +++ b/test/CodeGenCXX/microsoft-inaccessible-base.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fms-compatibility -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s + +// Make sure we choose the *direct* base path when doing these conversions. + +// CHECK: %struct.C = type { %struct.A, %struct.B } +// CHECK: %struct.D = type { %struct.B, %struct.A } + +struct A { int a; }; +struct B : A { int b; }; + +struct C : A, B { }; +extern "C" A *a_from_c(C *p) { return p; } +// CHECK-LABEL: define %struct.A* @a_from_c(%struct.C* %{{.*}}) +// CHECK: bitcast %struct.C* %{{.*}} to %struct.A* + +struct D : B, A { }; +extern "C" A *a_from_d(D *p) { return p; } +// CHECK-LABEL: define %struct.A* @a_from_d(%struct.D* %{{.*}}) +// CHECK: %[[p_i8:[^ ]*]] = bitcast %struct.D* %{{.*}} to i8* +// CHECK: getelementptr inbounds i8, i8* %[[p_i8]], i64 8 diff --git a/test/CodeGenCXX/mingw-w64-exceptions.c b/test/CodeGenCXX/mingw-w64-exceptions.c new file mode 100644 index 000000000000..e980ebd33505 --- /dev/null +++ b/test/CodeGenCXX/mingw-w64-exceptions.c @@ -0,0 +1,22 @@ +// RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SEH +// RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DWARF + +// RUN: %clang -target x86_64-windows-gnu -fsjlj-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SJLJ + +// RUN: %clang -target x86_64-windows-gnu -fdwarf-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-DWARF + +// RUN: %clang -target x86_64-windows-gnu -fsjlj-exceptions -fseh-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SEH + +// RUN: %clang -target x86_64-windows-gnu -fseh-exceptions -fsjlj-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SJLJ + +// RUN: %clang -target x86_64-windows-gnu -fseh-exceptions -fdwarf-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-DWARF + +// CHECK-SEH: "-fseh-exceptions" +// CHECK-SJLJ: "-fsjlj-exceptions" +// CHECK-DWARF-NOT: "-fsjlj-exceptions" +// CHECK-DWARF-NOT: "-fseh-exceptions" diff --git a/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp index 9025f877c551..046c4a815f46 100644 --- a/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp +++ b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 %s -fexceptions -fseh-exceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 %s -fexceptions -fdwarf-exceptions -emit-llvm -triple i686-w64-windows-gnu -o - | FileCheck %s --check-prefix=X86 // RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple i686-w64-windows-gnu -o - | FileCheck %s --check-prefix=X86 extern "C" void foo(); diff --git a/test/CodeGenCXX/ms-eh-personality.cpp b/test/CodeGenCXX/ms-eh-personality.cpp new file mode 100644 index 000000000000..592ab69efaf2 --- /dev/null +++ b/test/CodeGenCXX/ms-eh-personality.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fsjlj-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=SJLJ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fseh-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fdwarf-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=DWARF + +// MSVC: define void @f(){{.*}}@__CxxFrameHandler3 +// SJLJ: define void @f(){{.*}}@__gxx_personality_sj0 +// DWARF: define void @f(){{.*}}@__gxx_personality_v0 + +struct Cleanup { + Cleanup(); + ~Cleanup(); + int x = 0; +}; + +void g(); +extern "C" void f() { + Cleanup c; + g(); +} diff --git a/test/CodeGenCXX/ms-inline-asm-return.cpp b/test/CodeGenCXX/ms-inline-asm-return.cpp index 51671c0bcdaa..837f1b437a4c 100644 --- a/test/CodeGenCXX/ms-inline-asm-return.cpp +++ b/test/CodeGenCXX/ms-inline-asm-return.cpp @@ -70,7 +70,7 @@ FourChars f_s4() { } } // CHECK-LABEL: define i32 @f_s4() -// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$0x01010101", "={eax},~{eax},{{.*}}" +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$16843009", "={eax},~{eax},{{.*}}" // CHECK: store i32 %[[r]], i32* %{{.*}} // CHECK: %[[r_i32:[^ ]*]] = load i32, i32* %{{.*}} // CHECK: ret i32 %[[r_i32]] @@ -85,7 +85,7 @@ EightChars f_s8() { } } // CHECK-LABEL: define i64 @f_s8() -// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$01010101h\0A\09mov edx, $$01010101b", "=A,~{eax},{{.*}}" +// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$16843009\0A\09mov edx, $$85", "=A,~{eax},{{.*}}" // CHECK: store i64 %[[r]], i64* %{{.*}} // CHECK: %[[r_i64:[^ ]*]] = load i64, i64* %{{.*}} // CHECK: ret i64 %[[r_i64]] diff --git a/test/CodeGenCXX/new-overflow.cpp b/test/CodeGenCXX/new-overflow.cpp index 0c4c3c823d19..b27984f66ab6 100644 --- a/test/CodeGenCXX/new-overflow.cpp +++ b/test/CodeGenCXX/new-overflow.cpp @@ -85,9 +85,7 @@ namespace test4 { // CHECK: define [[A:%.*]]* @_ZN5test44testEs(i16 signext // CHECK: [[N:%.*]] = sext i16 {{%.*}} to i32 - // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0 - // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]] - // CHECK-NEXT: call i8* @_Znaj(i32 [[T1]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[N]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(short s) { return new elt[s]; @@ -104,9 +102,7 @@ namespace test5 { // CHECK: define [[A:%.*]]* @_ZN5test54testEi(i32 // CHECK: [[N:%.*]] = load i32, i32* - // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0 - // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]] - // CHECK-NEXT: call i8* @_Znaj(i32 [[T1]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[N]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(int s) { return new elt[s]; @@ -169,13 +165,11 @@ namespace test8 { // CHECK: define [[A:%.*]]* @_ZN5test84testEx(i64 // CHECK: [[N:%.*]] = load i64, i64* - // CHECK-NEXT: [[T0:%.*]] = icmp uge i64 [[N]], 4294967296 // CHECK-NEXT: [[T1:%.*]] = trunc i64 [[N]] to i32 // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[T1]], i32 4) // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 1 - // CHECK-NEXT: [[T4:%.*]] = or i1 [[T0]], [[T3]] // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0 - // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]] + // CHECK-NEXT: [[T6:%.*]] = select i1 [[T3]], i32 -1, i32 [[T5]] // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T1]] elt *test(long long s) { @@ -194,13 +188,11 @@ namespace test9 { // CHECK: define [[A:%.*]]* @_ZN5test94testEy(i64 // CHECK: [[N:%.*]] = load i64, i64* - // CHECK-NEXT: [[T0:%.*]] = icmp uge i64 [[N]], 4294967296 // CHECK-NEXT: [[T1:%.*]] = trunc i64 [[N]] to i32 // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[T1]], i32 4) // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 1 - // CHECK-NEXT: [[T4:%.*]] = or i1 [[T0]], [[T3]] // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0 - // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]] + // CHECK-NEXT: [[T6:%.*]] = select i1 [[T3]], i32 -1, i32 [[T5]] // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T1]] elt *test(unsigned long long s) { diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index ae2ec1505c5d..3bebc2ab8ac8 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -255,8 +255,6 @@ namespace test15 { // CHECK-LABEL: define void @_ZN6test155test2EPvi( // CHECK: [[N:%.*]] = load i32, i32* // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64 - // CHECK-NEXT: [[T1:%.*]] = icmp slt i64 [[T0]], 0 - // CHECK-NEXT: [[T2:%.*]] = select i1 [[T1]], i64 -1, i64 [[T0]] // CHECK-NEXT: [[P:%.*]] = load i8*, i8** // CHECK: [[BEGIN:%.*]] = bitcast i8* [[P]] to [[A:%.*]]* // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq i64 [[T0]], 0 diff --git a/test/CodeGenCXX/noescape.cpp b/test/CodeGenCXX/noescape.cpp new file mode 100644 index 000000000000..90d24de3da29 --- /dev/null +++ b/test/CodeGenCXX/noescape.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +struct S { + int a[4]; + S(int *, int * __attribute__((noescape))); + S &operator=(int * __attribute__((noescape))); + void m0(int *, int * __attribute__((noescape))); + virtual void vm1(int *, int * __attribute__((noescape))); +}; + +// CHECK: define void @_ZN1SC2EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture) +// CHECK: define void @_ZN1SC1EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture) {{.*}} { +// CHECK: call void @_ZN1SC2EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) + +S::S(int *, int * __attribute__((noescape))) {} + +// CHECK: define {{.*}} %struct.S* @_ZN1SaSEPi(%struct.S* {{.*}}, {{.*}} nocapture) +S &S::operator=(int * __attribute__((noescape))) { return *this; } + +// CHECK: define void @_ZN1S2m0EPiS0_(%struct.S* {{.*}}, {{.*}} nocapture) +void S::m0(int *, int * __attribute__((noescape))) {} + +// CHECK: define void @_ZN1S3vm1EPiS0_(%struct.S* {{.*}}, {{.*}} nocapture) +void S::vm1(int *, int * __attribute__((noescape))) {} + +// CHECK-LABEL: define void @_Z5test0P1SPiS1_( +// CHECK: call void @_ZN1SC1EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) +// CHECK: call {{.*}} %struct.S* @_ZN1SaSEPi(%struct.S* {{.*}}, {{.*}} nocapture {{.*}}) +// CHECK: call void @_ZN1S2m0EPiS0_(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) +// CHECK: call void {{.*}}(%struct.S* {{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) +void test0(S *s, int *p0, int *p1) { + S t(p0, p1); + t = p1; + s->m0(p0, p1); + s->vm1(p0, p1); +} + +namespace std { + typedef decltype(sizeof(0)) size_t; +} + +// CHECK: define {{.*}} @_ZnwmPv({{.*}}, {{.*}} nocapture {{.*}}) +void *operator new(std::size_t, void * __attribute__((noescape)) p) { + return p; +} + +// CHECK-LABEL: define i8* @_Z5test1Pv( +// CHECK : %call = call {{.*}} @_ZnwmPv({{.*}}, {{.*}} nocapture {{.*}}) +void *test1(void *p0) { + return ::operator new(16, p0); +} + +// CHECK-LABEL: define void @_Z5test2PiS_( +// CHECK: call void @"_ZZ5test2PiS_ENK3$_0clES_S_"({{.*}}, {{.*}}, {{.*}} nocapture {{.*}}) +// CHECK: define internal void @"_ZZ5test2PiS_ENK3$_0clES_S_"({{.*}}, {{.*}}, {{.*}} nocapture) +void test2(int *p0, int *p1) { + auto t = [](int *, int * __attribute__((noescape))){}; + t(p0, p1); +} + +// CHECK-LABEL: define void @_Z5test3PFvU8noescapePiES_( +// CHECK: call void {{.*}}(i32* nocapture {{.*}}) +typedef void (*NoEscapeFunc)(__attribute__((noescape)) int *); + +void test3(NoEscapeFunc f, int *p) { + f(p); +} diff --git a/test/CodeGenCXX/pr29160.cpp b/test/CodeGenCXX/pr29160.cpp new file mode 100644 index 000000000000..09cf2a637072 --- /dev/null +++ b/test/CodeGenCXX/pr29160.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu %s -o /dev/null -S -emit-llvm +// +// This test's failure mode is running ~forever. (For some value of "forever" +// that's greater than 25 minutes on my machine) + +template <typename... Ts> +struct Foo { + template <typename... T> + static void ignore() {} + Foo() { ignore<Ts...>(); } +}; + +struct Base { + Base(); + ~Base(); +}; + +#define STAMP(thiz, prev) using thiz = Foo< \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev \ + >; +STAMP(A, Base); +STAMP(B, A); +STAMP(C, B); +STAMP(D, C); +STAMP(E, D); +STAMP(F, E); +STAMP(G, F); +STAMP(H, G); +STAMP(I, H); +STAMP(J, I); +STAMP(K, J); +STAMP(L, K); +STAMP(M, L); +STAMP(N, M); +STAMP(O, N); +STAMP(P, O); +STAMP(Q, P); + +int main() { Q q; } diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp index 0ff6fdf12a58..2b7b9e2a6eff 100644 --- a/test/CodeGenCXX/regcall.cpp +++ b/test/CodeGenCXX/regcall.cpp @@ -73,8 +73,8 @@ bool __regcall operator ==(const test_class&, const test_class&){ --x; return fa // CHECK-WIN64-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NAEBVtest_class@@0@Z" // CHECK-WIN32-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NABVtest_class@@0@Z" -test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};} -// CHECK-LIN64-DAG: define x86_regcallcc %class.test_class @_Zli11_test_classy(i64) +test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};} +// CHECK-LIN64-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* noalias sret %agg.result, i64) // CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64) // CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z" // CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z" @@ -95,3 +95,11 @@ void force_gen() { freeTempFunc(1); t3.do_thing(); } + +long double _Complex __regcall foo(long double _Complex f) { + return f; +} +// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 16 %f) +// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %f) +// CHECK-WIN64-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1) +// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1) diff --git a/test/CodeGenCXX/rtti-mingw64.cpp b/test/CodeGenCXX/rtti-mingw64.cpp index 818b11b64bc5..9f3e03961e89 100644 --- a/test/CodeGenCXX/rtti-mingw64.cpp +++ b/test/CodeGenCXX/rtti-mingw64.cpp @@ -2,7 +2,12 @@ struct A { int a; }; struct B : virtual A { int b; }; B b; +class C { + virtual ~C(); +}; +C::~C() {} +// CHECK: @_ZTI1C = linkonce_odr // CHECK: @_ZTI1B = linkonce_odr constant { i8*, i8*, i32, i32, i8*, i64 } // CHECK-SAME: i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), // CHECK-SAME: i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1B, i32 0, i32 0), diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp index 76c002c0e407..8ccf0291687c 100644 --- a/test/CodeGenCXX/runtime-dllstorage.cpp +++ b/test/CodeGenCXX/runtime-dllstorage.cpp @@ -12,7 +12,7 @@ // %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IA-ATEXIT // %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA // RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA // RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA // RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA diff --git a/test/CodeGenCXX/sanitize-dtor-callback.cpp b/test/CodeGenCXX/sanitize-dtor-callback.cpp index e208a6f7e5a5..ecb0f2b2d13b 100644 --- a/test/CodeGenCXX/sanitize-dtor-callback.cpp +++ b/test/CodeGenCXX/sanitize-dtor-callback.cpp @@ -55,16 +55,19 @@ Defaulted_Non_Trivial def_non_trivial; // to confirm that all invoked dtors have member poisoning // instrumentation inserted. // CHECK-LABEL: define {{.*}}SimpleD2Ev +// CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void // CHECK-LABEL: define {{.*}}InlinedD2Ev +// CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void // CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD2Ev +// CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void diff --git a/test/CodeGenCXX/static-init-wasm.cpp b/test/CodeGenCXX/static-init-wasm.cpp index 289c3ea6024d..68d139157e2d 100644 --- a/test/CodeGenCXX/static-init-wasm.cpp +++ b/test/CodeGenCXX/static-init-wasm.cpp @@ -20,7 +20,7 @@ void g() { // WEBASSEMBLY32: %[[R0:.+]] = load atomic i8, i8* bitcast (i32* @_ZGVZ1gvE1a to i8*) acquire, align 4 // WEBASSEMBLY32-NEXT: %[[R1:.+]] = and i8 %[[R0]], 1 // WEBASSEMBLY32-NEXT: %[[R2:.+]] = icmp eq i8 %[[R1]], 0 -// WEBASSEMBLY32-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]] +// WEBASSEMBLY32-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]], // WEBASSEMBLY32: [[CHECK]] // WEBASSEMBLY32: call i32 @__cxa_guard_acquire // WEBASSEMBLY32: [[END]] @@ -30,7 +30,7 @@ void g() { // WEBASSEMBLY64: %[[R0:.+]] = load atomic i8, i8* bitcast (i64* @_ZGVZ1gvE1a to i8*) acquire, align 8 // WEBASSEMBLY64-NEXT: %[[R1:.+]] = and i8 %[[R0]], 1 // WEBASSEMBLY64-NEXT: %[[R2:.+]] = icmp eq i8 %[[R1]], 0 -// WEBASSEMBLY64-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]] +// WEBASSEMBLY64-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]], // WEBASSEMBLY64: [[CHECK]] // WEBASSEMBLY64: call i32 @__cxa_guard_acquire // WEBASSEMBLY64: [[END]] @@ -43,12 +43,12 @@ struct A { A theA; -// WEBASSEMBLY32: define internal void @__cxx_global_var_init() #3 section ".text.__startup" { +// WEBASSEMBLY32: define internal void @__cxx_global_var_init() #3 { // WEBASSEMBLY32: call %struct.A* @_ZN1AC1Ev(%struct.A* @theA) -// WEBASSEMBLY32: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #3 section ".text.__startup" { +// WEBASSEMBLY32: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #3 { // WEBASSEMBLY32: call void @__cxx_global_var_init() // -// WEBASSEMBLY64: define internal void @__cxx_global_var_init() #3 section ".text.__startup" { +// WEBASSEMBLY64: define internal void @__cxx_global_var_init() #3 { // WEBASSEMBLY64: call %struct.A* @_ZN1AC1Ev(%struct.A* @theA) -// WEBASSEMBLY64: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #3 section ".text.__startup" { +// WEBASSEMBLY64: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #3 { // WEBASSEMBLY64: call void @__cxx_global_var_init() diff --git a/test/CodeGenCXX/static-initializer-branch-weights.cpp b/test/CodeGenCXX/static-initializer-branch-weights.cpp new file mode 100644 index 000000000000..f9e77812714c --- /dev/null +++ b/test/CodeGenCXX/static-initializer-branch-weights.cpp @@ -0,0 +1,126 @@ +// RUN: %clang_cc1 -emit-llvm -std=c++1z %s -o - -triple=x86_64-linux-gnu | FileCheck %s + +struct S { S(); ~S(); }; + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK-NOT: br +// CHECK: call void @_ZN1SC1Ev({{.*}}* @global) +S global; + +// CHECK-LABEL: define {{.*}}global_var_init +// FIXME: Do we really need thread-safe initialization here? We don't run +// global ctors on multiple threads. (If we were to do so, we'd need thread-safe +// init for B<int>::member and B<int>::inline_member too.) +// CHECK: load atomic i8, i8* bitcast (i64* @_ZGV13inline_global to i8*) acquire, +// CHECK: icmp eq i8 {{.*}}, 0 +// CHECK: br i1 +// CHECK-NOT: !prof +// CHECK: call void @_ZN1SC1Ev({{.*}}* @inline_global) +inline S inline_global; + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK-NOT: br +// CHECK: call void @_ZN1SC1Ev({{.*}}* @thread_local_global) +thread_local S thread_local_global; + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK: load i8, i8* bitcast (i64* @_ZGV26thread_local_inline_global to i8*) +// CHECK: icmp eq i8 {{.*}}, 0 +// CHECK: br i1 +// CHECK-NOT: !prof +// CHECK: call void @_ZN1SC1Ev({{.*}}* @thread_local_inline_global) +thread_local inline S thread_local_inline_global; + +struct A { + static S member; + static thread_local S thread_local_member; + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load atomic i8, i8* bitcast (i64* @_ZGVN1A13inline_memberE to i8*) acquire, + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1A13inline_memberE) + static inline S inline_member; + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load i8, i8* bitcast (i64* @_ZGVN1A26thread_local_inline_memberE to i8*) + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1A26thread_local_inline_memberE) + static thread_local inline S thread_local_inline_member; +}; + +// CHECK-LABEL: define void @_Z1fv() +void f() { + // CHECK: load atomic i8, i8* bitcast (i64* @_ZGVZ1fvE12static_local to i8*) acquire, + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 {{.*}}, !prof ![[WEIGHTS_LOCAL:[0-9]*]] + static S static_local; + + // CHECK: load i8, i8* @_ZGVZ1fvE19static_thread_local, + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 {{.*}}, !prof ![[WEIGHTS_THREAD_LOCAL:[0-9]*]] + static thread_local S static_thread_local; +} + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK-NOT: br +// CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1A6memberE) +S A::member; + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK-NOT: br +// CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1A19thread_local_memberE) +thread_local S A::thread_local_member; + +template <typename T> struct B { + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load i8, i8* bitcast (i64* @_ZGVN1BIiE6memberE to i8*) + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1BIiE6memberE) + static S member; + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load i8, i8* bitcast (i64* @_ZGVN1BIiE13inline_memberE to i8*) + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1BIiE13inline_memberE) + static inline S inline_member; + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load i8, i8* bitcast (i64* @_ZGVN1BIiE19thread_local_memberE to i8*) + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1BIiE19thread_local_memberE) + static thread_local S thread_local_member; + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: load i8, i8* bitcast (i64* @_ZGVN1BIiE26thread_local_inline_memberE to i8*) + // CHECK: icmp eq i8 {{.*}}, 0 + // CHECK: br i1 + // CHECK-NOT: !prof + // CHECK: call void @_ZN1SC1Ev({{.*}}* @_ZN1BIiE26thread_local_inline_memberE) + static thread_local inline S thread_local_inline_member; +}; +template<typename T> S B<T>::member; +template<typename T> thread_local S B<T>::thread_local_member; + +template<typename ...T> void use(T &...); +void use_b() { + use(B<int>::member, B<int>::inline_member, B<int>::thread_local_member, + B<int>::thread_local_inline_member); +} + +// CHECK-LABEL: define {{.*}}tls_init() +// CHECK: load i8, i8* @__tls_guard, align 1 +// CHECK: icmp eq i8 {{.*}}, 0 +// CHECK: br i1 {{.*}}, !prof ![[WEIGHTS_THREAD_LOCAL]] + +// CHECK-DAG: ![[WEIGHTS_THREAD_LOCAL]] = !{!"branch_weights", i32 1, i32 1023} +// CHECK-DAG: ![[WEIGHTS_LOCAL]] = !{!"branch_weights", i32 1, i32 1048575} diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp index 5bd9908d6c25..4586a3c38fff 100644 --- a/test/CodeGenCXX/stmtexpr.cpp +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -173,7 +173,7 @@ extern "C" int cleanup_exit_lvalue_local(bool cond) { _Complex float bar_complex(A, int); extern "C" int cleanup_exit_complex(bool b) { _Complex float v = bar_complex(A(1), ({ if (b) return 42; 13; })); - return v; + return (float)v; } // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}}) diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index c3798920abdd..c45e7a60fa8f 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -53,7 +53,7 @@ struct DynamicFrom2Virtuals : }; // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv() -// CHECK-NEW-NOT: @llvm.invariant.group.barrier( +// CHECK-NEW-NOT: @llvm.invariant.group.barrier.p0i8( // CHECK-NEW-LABEL: {{^}}} void LocalObjects() { DynamicBase1 DB; @@ -81,20 +81,20 @@ void LocalObjects() { struct DynamicFromVirtualStatic1; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev -// CHECK-CTORS-NOT: @llvm.invariant.group.barrier( +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8( // CHECK-CTORS-LABEL: {{^}}} struct DynamicFrom2Virtuals; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev -// CHECK-CTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-CTORS: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-CTORS-LABEL: {{^}}} // CHECK-NEW-LABEL: define void @_Z9Pointers1v() -// CHECK-NEW-NOT: @llvm.invariant.group.barrier( +// CHECK-NEW-NOT: @llvm.invariant.group.barrier.p0i8( // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev( -// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS2:.*]]) +// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS2:.*]]) // CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]* // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* %[[THIS4]]) // CHECK-NEW-LABEL: {{^}}} @@ -109,9 +109,9 @@ void Pointers1() { // CHECK-NEW-LABEL: define void @_Z14HackingObjectsv() // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev -// CHECK-NEW: call i8* @llvm.invariant.group.barrier( +// CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev( -// CHECK-NEW: call i8* @llvm.invariant.group.barrier( +// CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev( // CHECK-NEW-LABEL: {{^}}} void HackingObjects() { @@ -131,7 +131,7 @@ void HackingObjects() { /*** Testing Constructors ***/ struct DynamicBase1; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev( -// CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-CTORS-LABEL: {{^}}} @@ -140,7 +140,7 @@ struct DynamicDerived; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev( // CHECK-CTORS: %[[THIS0:.*]] = load %[[DynamicDerived:.*]]*, %[[DynamicDerived]]** {{.*}} // CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0]] to i8* -// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1:.*]]) +// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS1:.*]]) // CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[DynamicDerived]]* // CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[DynamicDerived]]* %[[THIS3]] to %[[DynamicBase:.*]]* // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[DynamicBase]]* %[[THIS4]]) @@ -154,15 +154,15 @@ struct DynamicDerivedMultiple; // CHECK-CTORS: %[[THIS0:.*]] = load %[[CLASS:.*]]*, %[[CLASS]]** {{.*}} // CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0]] to i8* -// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1]]) +// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier.p0i8(i8* %[[THIS1]]) // CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[CLASS]]* // CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[CLASS]]* %[[THIS3]] to %[[BASE_CLASS:.*]]* // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[BASE_CLASS]]* %[[THIS4]]) -// CHECK-CTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-CTORS: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev( -// CHECK-CTORS-NOT: @llvm.invariant.group.barrier +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)*** @@ -177,7 +177,7 @@ struct DynamicDerivedMultiple; struct DynamicFromStatic; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev( -// CHECK-CTORS-NOT: @llvm.invariant.group.barrier( +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier.p0i8( // CHECK-CTORS-LABEL: {{^}}} struct A { @@ -206,15 +206,15 @@ void g2(A *a) { void UnionsBarriers(U *u) { // CHECK-NEW: call void @_Z9changeToBP1U( changeToB(u); - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z2g2P1A(%struct.A* g2(&u->b); // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* changeToA(u); - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // call void @_Z2g2P1A(%struct.A* %a) g2(&u->a); - // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8* } struct HoldingVirtuals { @@ -233,10 +233,10 @@ void take(AnotherEmpty &); // CHECK-NEW-LABEL: noBarriers void noBarriers(NoVptrs &noVptrs) { - // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: 42 noVptrs.a += 42; - // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z4takeR12AnotherEmpty( take(noVptrs.empty); } @@ -249,10 +249,10 @@ void take(HoldingVirtuals &); // CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2 void UnionsBarriers2(U2 &u) { - // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: 42 u.z += 42; - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals( take(u.h); } @@ -279,24 +279,24 @@ void take(VirtualInVBase &); void take(VirtualInheritance &); void UnionsBarrier3(U3 &u) { - // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: 42 u.z += 42; - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z4takeR13VirtualInBase( take(u.v1); - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z4takeR13VirtualInBase( take(u.v2); - // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call i8* @llvm.invariant.group.barrier.p0i8(i8* // CHECK-NEW: call void @_Z4takeR18VirtualInheritance( take(u.v3); } /** DTORS **/ // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev( -// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-DTORS-LABEL: {{^}}} @@ -305,22 +305,22 @@ void UnionsBarrier3(U3 &u) { // CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev -// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev( // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev( -// CHECK-DTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev -// CHECK-DTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev -// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier.p0i8( // CHECK-DTORS-LABEL: {{^}}} diff --git a/test/CodeGenCXX/tmp-md-nodes1.cpp b/test/CodeGenCXX/tmp-md-nodes1.cpp new file mode 100644 index 000000000000..41a0159b0fc4 --- /dev/null +++ b/test/CodeGenCXX/tmp-md-nodes1.cpp @@ -0,0 +1,18 @@ +// REQUIRES: asserts +// RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s + +// This test simply checks that the varargs thunk is created. The failing test +// case asserts. + +struct Alpha { + virtual void bravo(...); +}; +struct Charlie { + virtual ~Charlie() {} +}; +struct CharlieImpl : Charlie, Alpha { + void bravo(...) {} +} delta; + +// CHECK: define {{.*}} void @_ZThn{{[48]}}_N11CharlieImpl5bravoEz( diff --git a/test/CodeGenCXX/tmp-md-nodes2.cpp b/test/CodeGenCXX/tmp-md-nodes2.cpp new file mode 100644 index 000000000000..e50220cfb7c3 --- /dev/null +++ b/test/CodeGenCXX/tmp-md-nodes2.cpp @@ -0,0 +1,33 @@ +// REQUIRES: asserts +// RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s + +// This test simply checks that the varargs thunk is created. The failing test +// case asserts. + +typedef signed char __int8_t; +typedef int BOOL; +class CMsgAgent; + +class CFs { +public: + typedef enum {} CACHE_HINT; + virtual BOOL ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... ) ; +}; + +typedef struct {} _Lldiv_t; + +class CBdVfs { +public: + virtual ~CBdVfs( ) {} +}; + +class CBdVfsImpl : public CBdVfs, public CFs { + BOOL ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... ); +}; + +BOOL CBdVfsImpl::ReqCacheHint( CMsgAgent* p_ma, CACHE_HINT hint, ... ) { + return true; +} + +// CHECK: define {{.*}} @_ZThn{{[48]}}_N10CBdVfsImpl12ReqCacheHintEP9CMsgAgentN3CFs10CACHE_HINTEz( diff --git a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp index bc8861aa8314..f4ccdbf6474a 100644 --- a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp +++ b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s struct Base1 { virtual void f1() {} @@ -64,6 +64,11 @@ void t4() { // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED3]] {{.*}}, i{{[0-9]+}} %[[P1]] static_cast<Base1 *>(badp)->f1(); //< No devirt, test 'badp isa Base1'. + // We were able to skip the null check on the first type check because 'p' + // is backed by an alloca. We can't skip the second null check because 'badp' + // is a (bitcast (load ...)). + // CHECK: call void @__ubsan_handle_type_mismatch + // // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Base1* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]] {{.*}}, i{{[0-9]+}} %[[BADP1]] } @@ -76,6 +81,8 @@ void t5() { // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_1]] {{.*}}, i{{[0-9]+}} %[[P1]] static_cast<Base1 *>(badp)->f1(); //< Devirt Base1::f1 to Derived4::f1. + // CHECK: call void @__ubsan_handle_type_mismatch + // // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_2]] {{.*}}, i{{[0-9]+}} %[[BADP1]] } diff --git a/test/CodeGenCXX/ubsan-suppress-checks.cpp b/test/CodeGenCXX/ubsan-suppress-checks.cpp index ae7c94b34f29..fa7ea29d94f2 100644 --- a/test/CodeGenCXX/ubsan-suppress-checks.cpp +++ b/test/CodeGenCXX/ubsan-suppress-checks.cpp @@ -17,6 +17,17 @@ void load_non_null_pointers() { // CHECK: ret void } +// CHECK-LABEL: define void @_Z31use_us16_aligned_array_elementsv +void use_us16_aligned_array_elements() { + static const unsigned short Arr[] = {0, 1, 2}; + auto use_array = [](const unsigned short(&X)[3]) -> void {}; + use_array(Arr); + + // CHECK-NOT: br i1 true + // ALIGN-NOT: call void @__ubsan_handle_type_mismatch + // CHECK: ret void +} + struct A { int foo; @@ -229,4 +240,5 @@ void force_irgen() { d->load_member_3(); load_non_null_pointers(); + use_us16_aligned_array_elements(); } diff --git a/test/CodeGenCXX/ubsan-type-checks.cpp b/test/CodeGenCXX/ubsan-type-checks.cpp index 786d049dfb56..e53ab2466e73 100644 --- a/test/CodeGenCXX/ubsan-type-checks.cpp +++ b/test/CodeGenCXX/ubsan-type-checks.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null,vptr | FileCheck %s -check-prefixes=VPTR +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=vptr | FileCheck %s -check-prefixes=VPTR_NO_NULL struct A { // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv @@ -24,13 +26,60 @@ struct B { // NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize // OBJSIZE-NOT: call i64 @llvm.objectsize + // OBJSIZE: ret void } }; -void force_irgen() { +struct Animal { + virtual const char *speak() = 0; +}; + +struct Cat : Animal { + const char *speak() override { return "meow"; } +}; + +struct Dog : Animal { + const char *speak() override { return "woof"; } +}; + +// VPTR-LABEL: define void @_Z12invalid_castP3Cat +void invalid_cast(Cat *cat = nullptr) { + // If -fsanitize=null is available, we'll reuse its check: + // + // VPTR: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null + // VPTR-NEXT: br i1 [[ICMP]] + // VPTR: call void @__ubsan_handle_type_mismatch + // VPTR-NOT: icmp ne %struct.Dog* {{.*}}, null + // VPTR: br i1 [[ICMP]] + // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss + // + // Fall back to the vptr sanitizer's null check when -fsanitize=null isn't + // available. + // + // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch + // VPTR_NO_NULL: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null + // VPTR_NO_NULL-NEXT: br i1 [[ICMP]] + // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss + auto *badDog = reinterpret_cast<Dog *>(cat); + badDog->speak(); +} + +// VPTR_NO_NULL-LABEL: define void @_Z13invalid_cast2v +void invalid_cast2() { + // We've got a pointer to an alloca, so there's no run-time null check needed. + // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch + // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss + Cat cat; + cat.speak(); +} + +int main() { A a; a.do_nothing(); B b; b.do_nothing(); + + invalid_cast(); + return 0; } diff --git a/test/CodeGenCXX/ubsan-vtable-checks.cpp b/test/CodeGenCXX/ubsan-vtable-checks.cpp index e684ae9180f1..5e17913a2c89 100644 --- a/test/CodeGenCXX/ubsan-vtable-checks.cpp +++ b/test/CodeGenCXX/ubsan-vtable-checks.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=ITANIUM // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=MSABI -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM -// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI struct T { virtual ~T() {} virtual int v() { return 1; } diff --git a/test/CodeGenCXX/virt-dtor-key.cpp b/test/CodeGenCXX/virt-dtor-key.cpp index 40c5a537cc53..d1055d4e30ca 100644 --- a/test/CodeGenCXX/virt-dtor-key.cpp +++ b/test/CodeGenCXX/virt-dtor-key.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-windows-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MINGW // CHECK: @_ZTI3foo = constant +// CHECK-MINGW: @_ZTI3foo = linkonce_odr class foo { foo(); virtual ~foo(); diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp index 6ea234807ec2..20e4a1f45e3c 100644 --- a/test/CodeGenCXX/visibility-inlines-hidden.cpp +++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp @@ -162,3 +162,16 @@ namespace test6 { C::g(); } } + +namespace PR34811 { + template <typename T> void tf() {} + + // CHECK-LABEL: define linkonce_odr hidden i8* @_ZN7PR348111fEv( + inline void *f() { + auto l = []() {}; + // CHECK-LABEL: define linkonce_odr hidden void @_ZN7PR348112tfIZNS_1fEvEUlvE_EEvv( + return (void *)&tf<decltype(l)>; + } + + void *p = (void *)f; +} diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp index 957a9f9568b3..b8652f8329a5 100644 --- a/test/CodeGenCXX/vla.cpp +++ b/test/CodeGenCXX/vla.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck -check-prefixes=X64,CHECK %s +// RUN: %clang_cc1 -std=c++11 -triple amdgcn---amdgiz %s -emit-llvm -o - | FileCheck -check-prefixes=AMD,CHECK %s template<typename T> struct S { @@ -9,7 +10,7 @@ template<typename T> int S<T>::n = 5; int f() { // Make sure that the reference here is enough to trigger the instantiation of // the static data member. - // CHECK: @_ZN1SIiE1nE = linkonce_odr global i32 5 + // CHECK: @_ZN1SIiE1nE = linkonce_odr{{.*}} global i32 5 int a[S<int>::n]; return sizeof a; } @@ -17,10 +18,18 @@ int f() { // rdar://problem/9506377 void test0(void *array, int n) { // CHECK-LABEL: define void @_Z5test0Pvi( - // CHECK: [[ARRAY:%.*]] = alloca i8*, align 8 - // CHECK-NEXT: [[N:%.*]] = alloca i32, align 4 - // CHECK-NEXT: [[REF:%.*]] = alloca i16*, align 8 - // CHECK-NEXT: [[S:%.*]] = alloca i16, align 2 + // X64: [[ARRAY:%.*]] = alloca i8*, align 8 + // AMD: [[ARRAY0:%.*]] = alloca i8*, align 8, addrspace(5) + // AMD-NEXT: [[ARRAY:%.*]] = addrspacecast i8* addrspace(5)* [[ARRAY0]] to i8** + // X64-NEXT: [[N:%.*]] = alloca i32, align 4 + // AMD: [[N0:%.*]] = alloca i32, align 4, addrspace(5) + // AMD-NEXT: [[N:%.*]] = addrspacecast i32 addrspace(5)* [[N0]] to i32* + // X64-NEXT: [[REF:%.*]] = alloca i16*, align 8 + // AMD: [[REF0:%.*]] = alloca i16*, align 8, addrspace(5) + // AMD-NEXT: [[REF:%.*]] = addrspacecast i16* addrspace(5)* [[REF0]] to i16** + // X64-NEXT: [[S:%.*]] = alloca i16, align 2 + // AMD: [[S0:%.*]] = alloca i16, align 2, addrspace(5) + // AMD-NEXT: [[S:%.*]] = addrspacecast i16 addrspace(5)* [[S0]] to i16* // CHECK-NEXT: store i8* // CHECK-NEXT: store i32 @@ -59,6 +68,8 @@ void test0(void *array, int n) { void test2(int b) { // CHECK-LABEL: define void {{.*}}test2{{.*}}(i32 %b) int varr[b]; + // AMD: %__end = alloca i32*, align 8, addrspace(5) + // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32** // get the address of %b by checking the first store that stores it //CHECK: store i32 %b, i32* [[PTR_B:%.*]] @@ -75,13 +86,16 @@ void test2(int b) { //CHECK: [[VLA_SIZEOF:%.*]] = mul nuw i64 4, [[VLA_NUM_ELEMENTS_PRE]] //CHECK-NEXT: [[VLA_NUM_ELEMENTS_POST:%.*]] = udiv i64 [[VLA_SIZEOF]], 4 //CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_NUM_ELEMENTS_POST]] - //CHECK-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + //AMD-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]] for (int d : varr) 0; } void test3(int b, int c) { // CHECK-LABEL: define void {{.*}}test3{{.*}}(i32 %b, i32 %c) int varr[b][c]; + // AMD: %__end = alloca i32*, align 8, addrspace(5) + // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32** // get the address of %b by checking the first store that stores it //CHECK: store i32 %b, i32* [[PTR_B:%.*]] //CHECK-NEXT: store i32 %c, i32* [[PTR_C:%.*]] @@ -105,7 +119,8 @@ void test3(int b, int c) { //CHECK-NEXT: [[VLA_NUM_ELEMENTS:%.*]] = udiv i64 [[VLA_SIZEOF]], [[VLA_SIZEOF_DIM2]] //CHECK-NEXT: [[VLA_END_INDEX:%.*]] = mul nsw i64 [[VLA_NUM_ELEMENTS]], [[VLA_DIM2_PRE]] //CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_END_INDEX]] - //CHECK-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end + //AMD-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]] for (auto &d : varr) 0; } diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index 2e2cdbbfeff5..0e7e8b4a3226 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t diff --git a/test/CodeGenCXX/warn-padded-packed.cpp b/test/CodeGenCXX/warn-padded-packed.cpp index f2af60865e05..2cb049537348 100644 --- a/test/CodeGenCXX/warn-padded-packed.cpp +++ b/test/CodeGenCXX/warn-padded-packed.cpp @@ -17,7 +17,7 @@ struct S3 { } __attribute__((packed)); struct S4 { - int i; // expected-warning {{packed attribute is unnecessary for 'i'}} + int i; char c; } __attribute__((packed)); @@ -46,18 +46,18 @@ struct S8 : B { int i; // expected-warning {{padding struct 'S8' with 3 bytes to align 'i'}} }; -struct S9 { // expected-warning {{packed attribute is unnecessary for 'S9'}} - int x; // expected-warning {{packed attribute is unnecessary for 'x'}} - int y; // expected-warning {{packed attribute is unnecessary for 'y'}} +struct S9 { + int x; + int y; } __attribute__((packed)); -struct S10 { // expected-warning {{packed attribute is unnecessary for 'S10'}} - int x; // expected-warning {{packed attribute is unnecessary for 'x'}} +struct S10 { + int x; char a,b,c,d; } __attribute__((packed)); -struct S11 { +struct S11 { // expected-warning {{packed attribute is unnecessary for 'S11'}} bool x; char a,b,c,d; } __attribute__((packed)); @@ -72,5 +72,82 @@ struct S13 { // expected-warning {{padding size of 'S13' with 6 bits to alignmen bool b : 10; }; +struct S14 { // expected-warning {{packed attribute is unnecessary for 'S14'}} + char a,b,c,d; +} __attribute__((packed)); + +struct S15 { // expected-warning {{packed attribute is unnecessary for 'S15'}} + struct S14 s; + char a; +} __attribute__((packed)); + +struct S16 { // expected-warning {{padding size of 'S16' with 2 bytes to alignment boundary}} expected-warning {{packed attribute is unnecessary for 'S16'}} + char a,b; +} __attribute__((packed, aligned(4))); + +struct S17 { + struct S16 s; + char a,b; +} __attribute__((packed, aligned(2))); + +struct S18 { // expected-warning {{padding size of 'S18' with 2 bytes to alignment boundary}} expected-warning {{packed attribute is unnecessary for 'S18'}} + struct S16 s; + char a,b; +} __attribute__((packed, aligned(4))); + +struct S19 { // expected-warning {{packed attribute is unnecessary for 'S19'}} + bool b; + char a; +} __attribute__((packed, aligned(1))); + +struct S20 { + int i; + char a; +} __attribute__((packed, aligned(1))); + +struct S21 { // expected-warning {{padding size of 'S21' with 4 bits to alignment boundary}} + unsigned char a : 6; + unsigned char b : 6; +} __attribute__((packed, aligned(1))); + +struct S22 { // expected-warning {{packed attribute is unnecessary for 'S22'}} + unsigned char a : 4; + unsigned char b : 4; +} __attribute__((packed)); + +struct S23 { // expected-warning {{padding size of 'S23' with 4 bits to alignment boundary}} expected-warning {{packed attribute is unnecessary for 'S23'}} + unsigned char a : 2; + unsigned char b : 2; +} __attribute__((packed)); + +struct S24 { + unsigned char a : 6; + unsigned char b : 6; + unsigned char c : 6; + unsigned char d : 6; + unsigned char e : 6; + unsigned char f : 6; + unsigned char g : 6; + unsigned char h : 6; +} __attribute__((packed)); + +struct S25 { // expected-warning {{padding size of 'S25' with 7 bits to alignment boundary}} expected-warning {{packed attribute is unnecessary for 'S25'}} + unsigned char a; + unsigned char b : 1; +} __attribute__((packed)); + +struct S26 { // expected-warning {{packed attribute is unnecessary for 'S26'}} + unsigned char a : 1; + unsigned char b; //expected-warning {{padding struct 'S26' with 7 bits to align 'b'}} +} __attribute__((packed)); + +struct S27 { // expected-warning {{padding size of 'S27' with 7 bits to alignment boundary}} + unsigned char a : 1; + unsigned char b : 8; +} __attribute__((packed)); + + // The warnings are emitted when the layout of the structs is computed, so we have to use them. -void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*) { } +void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*, + S14*, S15*, S16*, S17*, S18*, S19*, S20*, S21*, S22*, S23*, S24*, S25*, + S26*, S27*){} |