diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
commit | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch) | |
tree | 47df2c12b57214af6c31e47404b005675b8b7ffc /test/CodeGenCXX | |
parent | f73d5f23a889b93d89ddef61ac0995df40286bb8 (diff) |
Notes
Diffstat (limited to 'test/CodeGenCXX')
336 files changed, 11185 insertions, 2358 deletions
diff --git a/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp b/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp index 3e5339732767e..a70f6e01280e6 100644 --- a/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp +++ b/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - +// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm %s -o - struct CallSite { diff --git a/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp b/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp index a6e2e30dd59bb..a4411fc468320 100644 --- a/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp +++ b/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - +// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm %s -o - struct A { virtual void Method() = 0; diff --git a/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp b/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp index 5d8c8b004b791..03c4ed623fdf2 100644 --- a/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp +++ b/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s // CHECK: _ZN11AccessFlags6strlenEv struct AccessFlags { diff --git a/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp b/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp index bd270dd602381..c5a2d5abc3efe 100644 --- a/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp +++ b/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s +// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm -o - %s struct A { virtual ~A(); diff --git a/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp b/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp index fe0740b7cb5c5..bf00c0f36bfe5 100644 --- a/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp +++ b/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s // CHECK-NOT: ZN12basic_stringIcEC1Ev // CHECK: ZN12basic_stringIcED1Ev diff --git a/test/CodeGenCXX/debug-info-class-limited.cpp b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp index a4b9f46ec6533..31a026101bb66 100644 --- a/test/CodeGenCXX/debug-info-class-limited.cpp +++ b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp @@ -1,16 +1,13 @@ -// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s -namespace PR16214_1 { -// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def] -struct foo { +// CHECK-DAG: [ DW_TAG_structure_type ] [PR16214] [line [[@LINE+1]], {{.*}} [def] +struct PR16214 { int i; }; -typedef foo bar; +typedef PR16214 bar; bar *a; bar b; -} namespace PR14467 { // CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def] @@ -24,7 +21,7 @@ foo *bar(foo *a) { } namespace test1 { -// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [decl] +// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def] struct foo { }; diff --git a/test/CodeGenCXX/PR19955.cpp b/test/CodeGenCXX/PR19955.cpp new file mode 100644 index 0000000000000..9e101550b419a --- /dev/null +++ b/test/CodeGenCXX/PR19955.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s --check-prefix X64 + +extern int __declspec(dllimport) var; +extern void __declspec(dllimport) fun(); + +extern int *varp; +int *varp = &var; +// CHECK-DAG: @"\01?varp@@3PAHA" = global i32* null +// X64-DAG: @"\01?varp@@3PEAHEA" = global i32* null + +extern void (*funp)(); +void (*funp)() = &fun; +// CHECK-DAG: @"\01?funp@@3P6AXXZA" = global void ()* null +// X64-DAG: @"\01?funp@@3P6AXXZEA" = global void ()* null + +// CHECK-LABEL: @"\01??__Evarp@@YAXXZ" +// CHECK-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PAHA" + +// X64-LABEL: @"\01??__Evarp@@YAXXZ" +// X64-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PEAHEA" + +// CHECK-LABEL: @"\01??__Efunp@@YAXXZ"() +// CHECK-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZA" + +// X64-LABEL: @"\01??__Efunp@@YAXXZ"() +// X64-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZEA" diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp new file mode 100644 index 0000000000000..c24685d696b64 --- /dev/null +++ b/test/CodeGenCXX/PR20038.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm %s -o - | FileCheck %s + +struct C { + ~C(); +}; +extern bool b; +// CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]] +// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]] +// CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1] +// CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2] +// CHECK: [[DTOR_CALL1_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN1_BLOCK:.*]], null} +// CHECK: [[FUN1_BLOCK]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN1]], +void fun1() { b && (C(), 1); } +// CHECK: [[DTOR_CALL2_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN2_BLOCK1:.*]], null} +// CHECK: [[FUN2_BLOCK1]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN2]], +bool fun2() { return (C(), b) && 0; } diff --git a/test/CodeGenCXX/PR5050-constructor-conversion.cpp b/test/CodeGenCXX/PR5050-constructor-conversion.cpp index a1b05ebc70b16..ce6cc0e846e20 100644 --- a/test/CodeGenCXX/PR5050-constructor-conversion.cpp +++ b/test/CodeGenCXX/PR5050-constructor-conversion.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s struct A { A(const A&, int i1 = 1); }; @@ -12,8 +11,4 @@ A f(const B &b) { return b; } -// CHECK-LP64: callq __ZN1AC1ERKS_i - -// CHECK-LP32: calll L__ZN1AC1ERKS_i - - +// CHECK: call void @_ZN1AC1ERKS_i diff --git a/test/CodeGenCXX/PR5093-static-member-function.cpp b/test/CodeGenCXX/PR5093-static-member-function.cpp index ceab8528e8bcb..d61a87ac16dc5 100644 --- a/test/CodeGenCXX/PR5093-static-member-function.cpp +++ b/test/CodeGenCXX/PR5093-static-member-function.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s struct a { static void f(); }; diff --git a/test/CodeGenCXX/PR5863-unreachable-block.cpp b/test/CodeGenCXX/PR5863-unreachable-block.cpp index 3f32d75704354..50d17314cb49b 100644 --- a/test/CodeGenCXX/PR5863-unreachable-block.cpp +++ b/test/CodeGenCXX/PR5863-unreachable-block.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm-only %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -emit-llvm-only %s // PR5863 class E { }; diff --git a/test/CodeGenCXX/aarch64-arguments.cpp b/test/CodeGenCXX/aarch64-arguments.cpp index f56ad0bbdcf3e..013051ccaea31 100644 --- a/test/CodeGenCXX/aarch64-arguments.cpp +++ b/test/CodeGenCXX/aarch64-arguments.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s +// RUN: %clang_cc1 -triple arm64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s // PCS: define void @{{.*}}(i8 %a struct s0 {}; diff --git a/test/CodeGenCXX/aarch64-cxxabi.cpp b/test/CodeGenCXX/aarch64-cxxabi.cpp index 04d9493ae6b08..6c08ff2fc3edd 100644 --- a/test/CodeGenCXX/aarch64-cxxabi.cpp +++ b/test/CodeGenCXX/aarch64-cxxabi.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s // Check differences between the generic Itanium ABI, the AArch32 version and // the AArch64 version. @@ -40,8 +40,8 @@ public: void guard_variables(int a) { static Guarded mine(a); -// CHECK: [[GUARDBIT:%[0-9]+]] = and i64 {{%[0-9]+}}, 1 -// CHECK: icmp eq i64 [[GUARDBIT]], 0 +// CHECK: [[GUARDBIT:%[0-9]+]] = and i8 {{%[0-9]+}}, 1 +// CHECK: icmp eq i8 [[GUARDBIT]], 0 // As guards are 64-bit, these helpers should take 64-bit pointers. // CHECK: call i32 @__cxa_guard_acquire(i64* diff --git a/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp index 2514704f1d886..3b4a309327fe6 100644 --- a/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp +++ b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp @@ -1,12 +1,11 @@ -// REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef signed char int8_t; typedef signed short int16_t; -typedef signed long long int64_t; -typedef unsigned long long uint64_t; +typedef signed long int64_t; +typedef unsigned long uint64_t; typedef unsigned char poly8_t; typedef unsigned short poly16_t; typedef __fp16 float16_t; diff --git a/test/CodeGenCXX/aarch64-neon.cpp b/test/CodeGenCXX/aarch64-neon.cpp index 5d2a00bebe737..d6f6b0e894fbf 100644 --- a/test/CodeGenCXX/aarch64-neon.cpp +++ b/test/CodeGenCXX/aarch64-neon.cpp @@ -1,13 +1,13 @@ // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon \ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ // RUN: -ffp-contract=fast -S -O3 -o - %s | FileCheck %s -// Test whether arm_neon.h can be used in .cpp file. +// Test whether arm_neon.h works as expected in C++. #include "arm_neon.h" poly64x1_t test_vld1_p64(poly64_t const * ptr) { // CHECK: test_vld1_p64 return vld1_p64(ptr); - // CHECK: ld1 {{{v[0-9]+}}.1d}, [{{x[0-9]+|sp}}] + // CHECK: {{ld1 { v[0-9]+.1d }|ldr d[0-9]+}}, [{{x[0-9]+|sp}}] } diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp index 793bbde050212..f36922413d83c 100644 --- a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp +++ b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp @@ -7,10 +7,10 @@ struct A { ~A(); }; -// CHECK-NOT-LABEL: define void @_ZN1AC1Ev +// CHECK-NOT: define void @_ZN1AC1Ev // CHECK-LABEL: define void @_ZN1AC2Ev -// CHECK-LABEL: define void @_ZN1AD1Ev // CHECK-LABEL: define void @_ZN1AD2Ev +// CHECK-LABEL: define void @_ZN1AD1Ev A::A() { } A::~A() { } diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp index 71794520f0a01..4ff597acb3047 100644 --- a/test/CodeGenCXX/address-of-fntemplate.cpp +++ b/test/CodeGenCXX/address-of-fntemplate.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s template <typename T> void f(T) {} template <typename T> void f() { } diff --git a/test/CodeGenCXX/address-space-ref.cpp b/test/CodeGenCXX/address-space-ref.cpp new file mode 100644 index 0000000000000..de6bddca66a72 --- /dev/null +++ b/test/CodeGenCXX/address-space-ref.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// For a reference to a complete type, output the dereferenceable attribute (in +// any address space). + +typedef int a __attribute__((address_space(1))); + +a & foo(a &x, a & y) { + return x; +} + +// CHECK: define dereferenceable(4) i32 addrspace(1)* @_Z3fooRU3AS1iS0_(i32 addrspace(1)* dereferenceable(4) %x, i32 addrspace(1)* dereferenceable(4) %y) + +// For a reference to an incomplete type in an alternate address space, output +// neither dereferenceable nor nonnull. + +class bc; +typedef bc b __attribute__((address_space(1))); + +b & bar(b &x, b & y) { + return x; +} + +// CHECK: define %class.bc addrspace(1)* @_Z3barRU3AS12bcS1_(%class.bc addrspace(1)* %x, %class.bc addrspace(1)* %y) + +// For a reference to an incomplete type in addrspace(0), output nonnull. + +bc & bar2(bc &x, bc & y) { + return x; +} + +// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y) + + diff --git a/test/CodeGenCXX/apple-kext.cpp b/test/CodeGenCXX/apple-kext.cpp index 03506a8aacf50..0d7ccfb3be1ae 100644 --- a/test/CodeGenCXX/apple-kext.cpp +++ b/test/CodeGenCXX/apple-kext.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fno-use-cxa-atexit -fapple-kext -emit-llvm -o - %s | FileCheck %s // CHECK: @_ZN5test01aE = global [[A:%.*]] zeroinitializer -// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]] } -// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]] } +// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]], i8* null } +// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]], i8* null } // rdar://11241230 namespace test0 { diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 2fb9c49bb7079..b6629f444e3fd 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios3.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s // CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4 // CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0 @@ -28,6 +28,7 @@ bar baz; // CHECK: call [[BAR:%.*]]* @_ZN3barC1Ev( // CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz) +// CHECK-NOT: @_GLOBAL__D_a() // CHECK-LABEL: define internal void @__dtor_baz() // CHECK: call [[BAR]]* @_ZN3barD1Ev([[BAR]]* @baz) @@ -292,9 +293,9 @@ namespace test7 { // CHECK-LABEL: define void @_ZN5test74testEv() void test() { - // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x - // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1 - // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 + // CHECK: [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test74testEvE1x to i8*) acquire, align 1 + // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1 + // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0 // CHECK-NEXT: br i1 [[T2]] // -> fallthrough, end // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x) @@ -327,9 +328,9 @@ namespace test8 { // CHECK-LABEL: define void @_ZN5test84testEv() void test() { - // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x - // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1 - // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 + // CHECK: [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test84testEvE1x to i8*) acquire, align 1 + // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1 + // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0 // CHECK-NEXT: br i1 [[T2]] // -> fallthrough, end // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x) @@ -416,6 +417,3 @@ namespace test9 { // CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev( // CHECK: call void @_ZN5test21CD0Ev( // CHECK: ret void - -// CH_ECK: @_GLOBAL__D_a() -// CH_ECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) diff --git a/test/CodeGenCXX/arm64-constructor-return.cpp b/test/CodeGenCXX/arm64-constructor-return.cpp new file mode 100644 index 0000000000000..0d5b3b38258c9 --- /dev/null +++ b/test/CodeGenCXX/arm64-constructor-return.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -triple=arm64-apple-ios7.0.0 -emit-llvm -o - | FileCheck %s +// rdar://12162905 + +struct S { + S(); + int iField; +}; + +S::S() { + iField = 1; +}; + +// 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: store %struct.S* %this, %struct.S** [[THISADDR]] +// CHECK: [[THIS1:%.*]] = load %struct.S** [[THISADDR]] +// CHECK: ret %struct.S* [[THIS1]] diff --git a/test/CodeGenCXX/arm64-darwinpcs.cpp b/test/CodeGenCXX/arm64-darwinpcs.cpp new file mode 100644 index 0000000000000..0a0ec3af49cfb --- /dev/null +++ b/test/CodeGenCXX/arm64-darwinpcs.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s -target-abi darwinpcs | FileCheck %s --check-prefix=CHECK-DARWIN + +void test_extensions(bool a, char b, short c) {} +// CHECK: define void @_Z15test_extensionsbcs(i1 %a, i8 %b, i16 %c) +// CHECK-DARWIN: define void @_Z15test_extensionsbcs(i1 zeroext %a, i8 signext %b, i16 signext %c) + +struct Empty {}; +void test_empty(Empty e) {} +// CHECK: define void @_Z10test_empty5Empty(i8 +// CHECK-DARWIN: define void @_Z10test_empty5Empty() + +struct HFA { + float a[3]; +}; diff --git a/test/CodeGenCXX/arm64-empty-struct.cpp b/test/CodeGenCXX/arm64-empty-struct.cpp new file mode 100644 index 0000000000000..6fa4e95295be0 --- /dev/null +++ b/test/CodeGenCXX/arm64-empty-struct.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s +struct Empty {}; + +Empty emptyvar; + +int take_args(int a, ...) { + __builtin_va_list l; + __builtin_va_start(l, a); +// CHECK: call void @llvm.va_start + + emptyvar = __builtin_va_arg(l, Empty); +// CHECK: load i8** +// CHECK-NOT: getelementptr +// CHECK: [[EMPTY_PTR:%[a-zA-Z0-9._]+]] = bitcast i8* {{%[a-zA-Z0-9._]+}} to %struct.Empty* + + // It's conceivable that EMPTY_PTR may not actually be a valid pointer + // (e.g. it's at the very bottom of the stack and the next page is + // invalid). This doesn't matter provided it's never loaded (there's no + // well-defined way to tell), but it becomes a problem if we do try to use it. +// CHECK-NOT: load %struct.Empty* [[EMPTY_PTR]] + + int i = __builtin_va_arg(l, int); +// CHECK: va_arg i8** {{%[a-zA-Z0-9._]+}}, i32 + + __builtin_va_end(l); + return i; +} diff --git a/test/CodeGenCXX/arm64.cpp b/test/CodeGenCXX/arm64.cpp new file mode 100644 index 0000000000000..d0d4f4f70efcd --- /dev/null +++ b/test/CodeGenCXX/arm64.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck -check-prefix=CHECK-GLOBALS %s + +// __cxa_guard_acquire argument is 64-bit +// rdar://11540122 +struct A { + A(); +}; + +void f() { + // CHECK: call i32 @__cxa_guard_acquire(i64* + static A a; +} + +// ARM64 uses the C++11 definition of POD. +// rdar://12650514 +namespace test1 { + // This class is POD in C++11 and cannot have objects allocated in + // its tail-padding. + struct ABase {}; + struct A : ABase { + int x; + char c; + }; + + struct B : A { + char d; + }; + + int test() { + return sizeof(B); + } + // CHECK: define i32 @_ZN5test14testEv() + // CHECK: ret i32 12 +} + +namespace std { + class type_info; +} + +// ARM64 uses string comparisons for what would otherwise be +// default-visibility weak RTTI. rdar://12650568 +namespace test2 { + struct A { + virtual void foo(); + }; + void A::foo() {} + // Tested below because these globals get kindof oddly rearranged. + + struct __attribute__((visibility("hidden"))) B {}; + const std::type_info &b0 = typeid(B); + // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21BE, i32 0, i32 0) } + + const std::type_info &b1 = typeid(B*); + // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([12 x i8]* @_ZTSPN5test21BE, i32 0, i32 0), i32 0, i8* bitcast + + struct C {}; + const std::type_info &c0 = typeid(C); + // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([11 x i8]* @_ZTSN5test21CE to i64), i64 -9223372036854775808) to i8*) } + + const std::type_info &c1 = typeid(C*); + // CHECK-GLOBALS: @_ZTSPN5test21CE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIPN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([12 x i8]* @_ZTSPN5test21CE to i64), i64 -9223372036854775808) to i8*), i32 0, i8* bitcast + + // This class is explicitly-instantiated, but that instantiation + // doesn't guarantee to emit RTTI, so we can still demote the visibility. + template <class T> class D {}; + template class D<int>; + const std::type_info &d0 = typeid(D<int>); + // CHECK-GLOBALS: @_ZTSN5test21DIiEE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIN5test21DIiEE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21DIiEE to i64), i64 -9223372036854775808) to i8*) } + + // This class is explicitly-instantiated and *does* guarantee to + // emit RTTI, so we're stuck with having to use default visibility. + template <class T> class E { + virtual void foo() {} + }; + template class E<int>; + // CHECK-GLOBALS: @_ZTSN5test21EIiEE = weak_odr constant [14 x i8] + // CHECK-GLOBALS: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) } + + // CHECK-GLOBALS: @_ZTSN5test21AE = constant [11 x i8] + // CHECK-GLOBALS: @_ZTIN5test21AE = constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21AE, i32 0, i32 0) } + +} diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp index 645ad1d787df7..53b81f2d85ba6 100644 --- a/test/CodeGenCXX/array-construction.cpp +++ b/test/CodeGenCXX/array-construction.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -31,7 +30,4 @@ int main() { h, i, j, array[h][i][j].i, array[h][i][j].f); } -// CHECK-LP64: callq __ZN4xptoC1Ev - -// CHECK-LP32: calll L__ZN4xptoC1Ev - +// CHECK: call void @_ZN4xptoC1Ev diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp index 8d6f50fdfab1b..890b142c10f84 100644 --- a/test/CodeGenCXX/array-operator-delete-call.cpp +++ b/test/CodeGenCXX/array-operator-delete-call.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -58,7 +57,5 @@ int main() } COST c2; -// CHECK-LP64: callq __ZdaPv - -// CHECK-LP32: calll L__ZdaPv +// CHECK: call void @_ZdaPv diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp index ee2e9e4cf2444..f453194468dd0 100644 --- a/test/CodeGenCXX/atomicinit.cpp +++ b/test/CodeGenCXX/atomicinit.cpp @@ -1,4 +1,10 @@ -// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s + +// CHECK-DAG: @_ZN7PR180978constant1aE = global {{.*}} { i16 1, i8 6, i8 undef }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1bE = global {{.*}} { i16 2, i8 6, i8 undef }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1cE = global {{.*}} { i16 3, i8 6, i8 undef }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1yE = global {{.*}} { {{.*}} { i16 4, i8 6, i8 undef }, i32 5 }, align 4 + struct A { _Atomic(int) i; A(int j); @@ -46,3 +52,51 @@ struct AtomicBoolMember { // CHECK-NEXT: ret void AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { } +namespace PR18097 { + namespace dynamic { + struct X { + X(int); + short n; + char c; + }; + + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1aE, i32 1) + _Atomic(X) a = X(1); + + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1bE, i32 2) + _Atomic(X) b(X(2)); + + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1cE, i32 3) + _Atomic(X) c{X(3)}; + + struct Y { + _Atomic(X) a; + _Atomic(int) b; + }; + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 0), i32 4) + // CHECK: store i32 5, i32* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 1) + Y y = { X(4), 5 }; + } + + // CHECKs at top of file. + namespace constant { + struct X { + constexpr X(int n) : n(n) {} + short n; + char c = 6; + }; + _Atomic(X) a = X(1); + _Atomic(X) b(X(2)); + _Atomic(X) c{X(3)}; + + struct Y { + _Atomic(X) a; + _Atomic(int) b; + }; + Y y = { X(4), 5 }; + } +} diff --git a/test/CodeGenCXX/attr-cleanup.cpp b/test/CodeGenCXX/attr-cleanup.cpp index ff15b03de57c5..18a7798481e9c 100644 --- a/test/CodeGenCXX/attr-cleanup.cpp +++ b/test/CodeGenCXX/attr-cleanup.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s namespace N { void free(void *i) {} diff --git a/test/CodeGenCXX/attr-used.cpp b/test/CodeGenCXX/attr-used.cpp index 2c82184081b91..8617346673575 100644 --- a/test/CodeGenCXX/attr-used.cpp +++ b/test/CodeGenCXX/attr-used.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s // <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors struct X0 { @@ -7,3 +7,21 @@ struct X0 { // CHECK: define linkonce_odr {{.*}} @_ZN2X0D1Ev __attribute__((used)) ~X0() {} }; + +// PR19743: not emitting __attribute__((used)) inline methods in nested classes. +struct X1 { + struct Nested { + // CHECK: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv + void __attribute__((used)) f() {} + }; +}; + +struct X2 { + // We must delay emission of bar() until foo() has had its body parsed, + // otherwise foo() would not be emitted. + void __attribute__((used)) bar() { foo(); } + void foo() { } + + // CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv + // CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv +}; diff --git a/test/CodeGenCXX/bitfield-layout.cpp b/test/CodeGenCXX/bitfield-layout.cpp index 646300a7d1cb7..46f41111a1de2 100644 --- a/test/CodeGenCXX/bitfield-layout.cpp +++ b/test/CodeGenCXX/bitfield-layout.cpp @@ -12,7 +12,7 @@ union Test2 { int : 6; } t2; -// CHECK-LP64: %union.Test3 = type { [2 x i8] } +// CHECK-LP64: %union.Test3 = type { i16 } union Test3 { int : 9; } t3; diff --git a/test/CodeGenCXX/bitfield.cpp b/test/CodeGenCXX/bitfield.cpp index 2c454b0c072c1..fafeffe1ed239 100644 --- a/test/CodeGenCXX/bitfield.cpp +++ b/test/CodeGenCXX/bitfield.cpp @@ -298,7 +298,7 @@ namespace N4 { #endif unsigned read(Base* s) { // FIXME: We should widen this load as long as the function isn't being - // instrumented by thread-sanitizer. + // instrumented by ThreadSanitizer. // // CHECK-X86-64-LABEL: define i32 @_ZN2N44read // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 @@ -378,8 +378,8 @@ namespace N6 { // Zero-length bitfields partition the memory locations of bitfields for the // purposes of the memory model. That means stores must not span zero-length // bitfields and loads may only span them when we are not instrumenting with - // thread sanitizer. - // FIXME: We currently don't widen loads even without thread sanitizer, even + // ThreadSanitizer. + // FIXME: We currently don't widen loads even without ThreadSanitizer, even // though we could. struct S { unsigned b1 : 24; @@ -426,3 +426,55 @@ namespace N6 { s->b2 = x; } } + +namespace N7 { + // Similar to N4 except that this adds a virtual base to the picture. (PR18430) + // Do NOT widen loads and stores to bitfields into padding at the end of + // a class which might end up with members inside of it when inside a derived + // class. + struct B1 { + virtual void f(); + unsigned b1 : 24; + }; + struct B2 : virtual B1 { + virtual ~B2(); + unsigned b : 24; + }; + // Imagine some other translation unit introduces: +#if 0 + struct Derived : public B2 { + char c; + }; +#endif + unsigned read(B2* s) { + // FIXME: We should widen this load as long as the function isn't being + // instrumented by ThreadSanitizer. + // + // CHECK-X86-64-LABEL: define i32 @_ZN2N74read + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-X86-64: %[[val:.*]] = load i24* %[[ptr]] + // CHECK-X86-64: %[[ext:.*]] = zext i24 %[[val]] to i32 + // CHECK-X86-64: ret i32 %[[ext]] + // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N74read + // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-PPC64: %[[val:.*]] = load i24* %[[ptr]] + // CHECK-PPC64: %[[ext:.*]] = zext i24 %[[val]] to i32 + // CHECK-PPC64: ret i32 %[[ext]] + return s->b; + } + void write(B2* s, unsigned x) { + // CHECK-X86-64-LABEL: define void @_ZN2N75write + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-X86-64: %[[new:.*]] = trunc i32 %{{.*}} to i24 + // CHECK-X86-64: store i24 %[[new]], i24* %[[ptr]] + // CHECK-PPC64-LABEL: define void @_ZN2N75write + // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-PPC64: %[[new:.*]] = trunc i32 %{{.*}} to i24 + // CHECK-PPC64: store i24 %[[new]], i24* %[[ptr]] + s->b = x; + } +} diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp index 616fd67ccc384..5c35ad72a20da 100644 --- a/test/CodeGenCXX/block-byref-cxx-objc.cpp +++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -fblocks | FileCheck %s // rdar://8594790 struct A { diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp index bd37d4418d4f0..0dc0ab00437fa 100644 --- a/test/CodeGenCXX/block-in-ctor-dtor.cpp +++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp @@ -40,9 +40,9 @@ X::~X() { // CHECK-LABEL: define internal void @___ZN4ZoneC2Ev_block_invoke_ // CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke // CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_ -// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke -// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_ // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_ +// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke +// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_ // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_ diff --git a/test/CodeGenCXX/block.cpp b/test/CodeGenCXX/block.cpp index 619d8b0c7ba4d..aa356688dd630 100644 --- a/test/CodeGenCXX/block.cpp +++ b/test/CodeGenCXX/block.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - -fblocks +// RUN: %clang_cc1 %s -triple %ms_abi_triple -fno-rtti -emit-llvm -o - -fblocks // Just test that this doesn't crash the compiler... void func(void*); diff --git a/test/CodeGenCXX/blocks-cxx11.cpp b/test/CodeGenCXX/blocks-cxx11.cpp index 9ff5826ec5f19..10d1c655d1f9a 100644 --- a/test/CodeGenCXX/blocks-cxx11.cpp +++ b/test/CodeGenCXX/blocks-cxx11.cpp @@ -106,7 +106,7 @@ namespace test_block_in_lambda { // CHECK: [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 0 - // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* [[T1]]) + // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* dereferenceable({{[0-9]+}}) [[T1]]) // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* // CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]]) // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]]) diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp index 8a6fdacf8d1f7..6b11083ad739d 100644 --- a/test/CodeGenCXX/blocks.cpp +++ b/test/CodeGenCXX/blocks.cpp @@ -164,7 +164,7 @@ namespace test5 { // CHECK-NOT: br // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 - // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* [[X]]) + // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* dereferenceable({{[0-9]+}}) [[X]]) // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* // CHECK-NEXT: br label diff --git a/test/CodeGenCXX/c-linkage.cpp b/test/CodeGenCXX/c-linkage.cpp index 1607623c6fea2..2f8729e4971a3 100644 --- a/test/CodeGenCXX/c-linkage.cpp +++ b/test/CodeGenCXX/c-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s // pr6644 extern "C" { @@ -10,7 +10,7 @@ extern "C" { } } -// CHECK-LABEL: define void @_ZN1N1X1fEv +// CHECK-LABEL: define {{.*}}void @_ZN1N1X1fEv extern "C" { static void test2_f() { diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp index 14238f2145155..beef2fd94a234 100644 --- a/test/CodeGenCXX/call-arg-zero-temp.cpp +++ b/test/CodeGenCXX/call-arg-zero-temp.cpp @@ -1,4 +1,4 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target +// REQUIRES: x86-registered-target // RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s // RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s // RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp index 2843c2b69c956..fb35446c7e981 100644 --- a/test/CodeGenCXX/captured-statements.cpp +++ b/test/CodeGenCXX/captured-statements.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3 diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp index 5565f6548437f..ce8f82089e1a0 100644 --- a/test/CodeGenCXX/cast-conversion.cpp +++ b/test/CodeGenCXX/cast-conversion.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s struct A { A(int); @@ -18,16 +17,9 @@ int main () { static_cast<B>(10); } -// CHECK-LP64: callq __ZN1AC1Ei -// CHECK-LP64: callq __ZN1BC1E1A -// CHECK-LP64: callq __ZN1AC1Ei -// CHECK-LP64: callq __ZN1BC1E1A -// CHECK-LP64: callq __ZN1AC1Ei -// CHECK-LP64: callq __ZN1BC1E1A - -// CHECK-LP32: calll L__ZN1AC1Ei -// CHECK-LP32: calll L__ZN1BC1E1A -// CHECK-LP32: calll L__ZN1AC1Ei -// CHECK-LP32: calll L__ZN1BC1E1A -// CHECK-LP32: calll L__ZN1AC1Ei -// CHECK-LP32: calll L__ZN1BC1E1A +// CHECK: call void @_ZN1AC1Ei +// CHECK: call void @_ZN1BC1E1A +// CHECK: call void @_ZN1AC1Ei +// CHECK: call void @_ZN1BC1E1A +// CHECK: call void @_ZN1AC1Ei +// CHECK: call void @_ZN1BC1E1A diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index 338da57f0c7ba..333855d0ba612 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL struct S { double d; @@ -6,9 +8,15 @@ struct S { virtual int f(); }; +// Check that type descriptor global is not modified by ASan. +// CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" } + +// 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]], {{.*}} } + struct T : S {}; -// CHECK: @_Z17reference_binding +// CHECK-LABEL: @_Z17reference_binding void reference_binding(int *p, S *q) { // C++ core issue 453: If an lvalue to which a reference is directly bound // designates neither an existing object or function of an appropriate type, @@ -30,7 +38,8 @@ void reference_binding(int *p, S *q) { S &r2 = *q; } -// CHECK: @_Z13member_access +// CHECK-LABEL: @_Z13member_access +// CHECK-ASAN-LABEL: @_Z13member_access void member_access(S *p) { // (1a) Check 'p' is appropriately sized and aligned for member access. @@ -117,7 +126,7 @@ void member_access(S *p) { k = p->f(); } -// CHECK: @_Z12lsh_overflow +// CHECK-LABEL: @_Z12lsh_overflow int lsh_overflow(int a, int b) { // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 // CHECK-NEXT: br i1 %[[INBOUNDS]] @@ -142,13 +151,13 @@ int lsh_overflow(int a, int b) { return a << b; } -// CHECK: @_Z9no_return +// CHECK-LABEL: @_Z9no_return int no_return() { // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) [[NR_NUW:#[0-9]+]] // CHECK-NEXT: unreachable } -// CHECK: @_Z9sour_bool +// CHECK-LABEL: @_Z9sour_bool bool sour_bool(bool *p) { // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 // CHECK: br i1 %[[OK]] @@ -160,7 +169,7 @@ enum E1 { e1a = 0, e1b = 127 } e1; enum E2 { e2a = -1, e2b = 64 } e2; enum E3 { e3a = (1u << 31) - 1 } e3; -// CHECK: @_Z14bad_enum_value +// CHECK-LABEL: @_Z14bad_enum_value int bad_enum_value() { // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127 // CHECK: br i1 %[[E1]] @@ -181,11 +190,16 @@ int bad_enum_value() { return a + b + c; } -// CHECK: @_Z20bad_downcast_pointer +// CHECK-LABEL: @_Z20bad_downcast_pointer +// DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer void bad_downcast_pointer(S *p) { // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null // CHECK: br i1 %[[NONNULL]], + // A null poiner access is guarded without -fsanitize=null. + // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null + // DOWNCAST-NULL: br i1 %[[NONNULL]], + // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8( // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24 // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 @@ -203,7 +217,7 @@ void bad_downcast_pointer(S *p) { (void) static_cast<T*>(p); } -// CHECK: @_Z22bad_downcast_reference +// CHECK-LABEL: @_Z22bad_downcast_reference void bad_downcast_reference(S &p) { // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null // CHECK-NOT: br i1 @@ -225,7 +239,7 @@ void bad_downcast_reference(S &p) { (void) static_cast<T&>(p); } -// CHECK: @_Z11array_index +// CHECK-LABEL: @_Z11array_index int array_index(const int (&a)[4], int n) { // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4 // CHECK: br i1 %[[K1_OK]] @@ -250,7 +264,7 @@ int array_index(const int (&a)[4], int n) { return k1 + *r1 + k2; } -// CHECK: @_Z17multi_array_index +// CHECK-LABEL: @_Z17multi_array_index int multi_array_index(int n, int m) { int arr[4][6]; @@ -264,7 +278,7 @@ int multi_array_index(int n, int m) { return arr[n][m]; } -// CHECK: @_Z11array_arith +// CHECK-LABEL: @_Z11array_arith int array_arith(const int (&a)[4], int n) { // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4 // CHECK: br i1 %[[K1_OK]] @@ -283,7 +297,7 @@ struct ArrayMembers { int a1[5]; int a2[1]; }; -// CHECK: @_Z18struct_array_index +// CHECK-LABEL: @_Z18struct_array_index int struct_array_index(ArrayMembers *p, int n) { // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5 // CHECK: br i1 %[[IDX_OK]] @@ -291,21 +305,21 @@ int struct_array_index(ArrayMembers *p, int n) { return p->a1[n]; } -// CHECK: @_Z16flex_array_index +// CHECK-LABEL: @_Z16flex_array_index int flex_array_index(ArrayMembers *p, int n) { // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( return p->a2[n]; } extern int incomplete[]; -// CHECK: @_Z22incomplete_array_index +// CHECK-LABEL: @_Z22incomplete_array_index int incomplete_array_index(int n) { // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( return incomplete[n]; } typedef __attribute__((ext_vector_type(4))) int V4I; -// CHECK: @_Z12vector_index +// CHECK-LABEL: @_Z12vector_index int vector_index(V4I v, int n) { // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4 // CHECK: br i1 %[[IDX_OK]] @@ -313,7 +327,7 @@ int vector_index(V4I v, int n) { return v[n]; } -// CHECK: @_Z12string_index +// CHECK-LABEL: @_Z12string_index char string_index(int n) { // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6 // CHECK: br i1 %[[IDX_OK]] @@ -357,7 +371,7 @@ void downcast_pointer(B *b) { // CHECK-NEXT: br i1 [[AND]] } -// CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* %b) +// CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* dereferenceable({{[0-9]+}}) %b) void downcast_reference(B &b) { (void) static_cast<C&>(b); // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...) diff --git a/test/CodeGenCXX/class-layout.cpp b/test/CodeGenCXX/class-layout.cpp index 21e1a2b40f04c..d7d84a86abad0 100644 --- a/test/CodeGenCXX/class-layout.cpp +++ b/test/CodeGenCXX/class-layout.cpp @@ -39,7 +39,7 @@ namespace Test5 { char a; }; - // CHECK: %"struct.Test5::B" = type { [9 x i8], i8, i8, [5 x i8] } + // CHECK: %"struct.Test5::B" = type { %"struct.Test5::A.base", i8, i8, [5 x i8] } struct B : A { char b : 1; char c; @@ -91,3 +91,12 @@ namespace Test7 { B* b; #pragma pack () } + +// Shouldn't crash. +namespace Test8 { + struct A {}; + struct D { int a; }; + struct B : virtual D, A { }; + struct C : B, A { void f() {} }; + C c; +} diff --git a/test/CodeGenCXX/conditional-gnu-ext.cpp b/test/CodeGenCXX/conditional-gnu-ext.cpp index 44ebf9808e4a2..3a61a63cf4493 100644 --- a/test/CodeGenCXX/conditional-gnu-ext.cpp +++ b/test/CodeGenCXX/conditional-gnu-ext.cpp @@ -83,7 +83,7 @@ namespace test3 { // CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]] // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]]) // CHECK-NEXT: br i1 [[BOOL]] - // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[T0]]) + // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[T0]]) // CHECK-NEXT: br label // CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]]) // CHECK-NEXT: br label @@ -97,7 +97,7 @@ namespace test3 { // CHECK-NEXT: call void @_ZN5test312test1_helperEv([[B]]* sret [[TEMP]]) // CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]]) // CHECK-NEXT: br i1 [[BOOL]] - // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[TEMP]]) + // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[TEMP]]) // CHECK-NEXT: br label // CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]]) // CHECK-NEXT: br label diff --git a/test/CodeGenCXX/const-base-cast.cpp b/test/CodeGenCXX/const-base-cast.cpp index 320c790c5e2d7..dd980d5469bf4 100644 --- a/test/CodeGenCXX/const-base-cast.cpp +++ b/test/CodeGenCXX/const-base-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s // Check that the following construct, which is similar to one which occurs // in Firefox, is folded correctly. diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp index df78fdd0287cc..e1e9321974792 100644 --- a/test/CodeGenCXX/const-global-linkage.cpp +++ b/test/CodeGenCXX/const-global-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s const int x = 10; const int y = 20; diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index d21e91178e407..f671e0ad88020 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -382,17 +382,22 @@ namespace ArrayTemporary { namespace UnemittedTemporaryDecl { constexpr int &&ref = 0; extern constexpr int &ref2 = ref; - // CHECK: @_ZGRN22UnemittedTemporaryDecl3refE = private global i32 0 + // CHECK: @_ZGRN22UnemittedTemporaryDecl3refE_ = private global i32 0 // FIXME: This declaration should not be emitted -- it isn't odr-used. // CHECK: @_ZN22UnemittedTemporaryDecl3refE - // CHECK: @_ZN22UnemittedTemporaryDecl4ref2E = constant i32* @_ZGRN22UnemittedTemporaryDecl3refE + // CHECK: @_ZN22UnemittedTemporaryDecl4ref2E = constant i32* @_ZGRN22UnemittedTemporaryDecl3refE_ } // CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101 // CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102 // CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103 +// CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ = linkonce_odr constant i32 5 +// CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ +// CHECK: @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ = linkonce_odr hidden constant i32 5 +// CHECK: @_ZN39ClassTemplateWithHiddenStaticDataMember3useE = constant i32* @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ +// CHECK: @_ZGRZN20InlineStaticConstRef3funEvE1i_ = linkonce_odr constant i32 10 // Constant initialization tests go before this point, // dynamic initialization tests go after. @@ -527,10 +532,10 @@ namespace InitFromConst { // CHECK: call void @_ZN13InitFromConst7consumeIdEEvT_(double 4.300000e+00) consume(d); - // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE) + // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* dereferenceable({{[0-9]+}}) @_ZN13InitFromConstL1sE) consume<const S&>(s); - // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE) + // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* dereferenceable({{[0-9]+}}) @_ZN13InitFromConstL1sE) consume<const S&>(r); // CHECK: call void @_ZN13InitFromConst7consumeIPKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE) @@ -552,3 +557,32 @@ namespace Null { // CHECK: call {{.*}} @_ZN4Null4nullEv( int S::*q = null(); } + +namespace InlineStaticConstRef { + inline const int &fun() { + static const int &i = 10; + return i; + // CHECK: ret i32* @_ZGRZN20InlineStaticConstRef3funEvE1i_ + } + const int &use = fun(); +} + +namespace ClassTemplateWithStaticDataMember { + template <typename T> + struct S { + static const int &a; + }; + template <typename T> + const int &S<T>::a = 5; + const int &use = S<void>::a; +} + +namespace ClassTemplateWithHiddenStaticDataMember { + template <typename T> + struct S { + __attribute__((visibility("hidden"))) static const int &a; + }; + template <typename T> + const int &S<T>::a = 5; + const int &use = S<void>::a; +} diff --git a/test/CodeGenCXX/const-init-cxx1y.cpp b/test/CodeGenCXX/const-init-cxx1y.cpp index 978c428e078a9..9348b43f486f1 100644 --- a/test/CodeGenCXX/const-init-cxx1y.cpp +++ b/test/CodeGenCXX/const-init-cxx1y.cpp @@ -1,4 +1,5 @@ -// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++1y | FileCheck %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++1y | FileCheck %s +// expected-no-diagnostics struct A { constexpr A() : n(1) {} @@ -22,26 +23,64 @@ namespace ModifyStaticTemporary { struct A { int &&temporary; int x; }; constexpr int f(int &r) { r *= 9; return r - 12; } A a = { 6, f(a.temporary) }; - // CHECK: @_ZGRN21ModifyStaticTemporary1aE = private global i32 54 - // CHECK: @_ZN21ModifyStaticTemporary1aE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1aE, i32 42 + // CHECK: @_ZGRN21ModifyStaticTemporary1aE_ = private global i32 54 + // CHECK: @_ZN21ModifyStaticTemporary1aE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1aE_, i32 42 A b = { 7, ++b.temporary }; - // CHECK: @_ZGRN21ModifyStaticTemporary1bE = private global i32 8 - // CHECK: @_ZN21ModifyStaticTemporary1bE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1bE, i32 8 + // CHECK: @_ZGRN21ModifyStaticTemporary1bE_ = private global i32 8 + // CHECK: @_ZN21ModifyStaticTemporary1bE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1bE_, i32 8 // Can't emit all of 'c' as a constant here, so emit the initial value of // 'c.temporary', not the value as modified by the partial evaluation within // the initialization of 'c.x'. A c = { 10, (++c.temporary, b.x) }; - // CHECK: @_ZGRN21ModifyStaticTemporary1cE = private global i32 10 + // CHECK: @_ZGRN21ModifyStaticTemporary1cE_ = private global i32 10 // CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer } +// CHECK: @_ZGRN28VariableTemplateWithConstRef1iIvEE_ = linkonce_odr constant i32 5, align 4 +// CHECK: @_ZN28VariableTemplateWithConstRef3useE = constant i32* @_ZGRN28VariableTemplateWithConstRef1iIvEE_ +namespace VariableTemplateWithConstRef { + template <typename T> + const int &i = 5; + const int &use = i<void>; +} + +// CHECK: @_ZGRN34HiddenVariableTemplateWithConstRef1iIvEE_ = linkonce_odr hidden constant i32 5, align 4 +// CHECK: @_ZN34HiddenVariableTemplateWithConstRef3useE = constant i32* @_ZGRN34HiddenVariableTemplateWithConstRef1iIvEE_ +namespace HiddenVariableTemplateWithConstRef { + template <typename T> + __attribute__((visibility("hidden"))) const int &i = 5; + const int &use = i<void>; +} + +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1_ = linkonce_odr constant i32 1 +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1_ } +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3_ = linkonce_odr constant i32 2 +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3_ } +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5_ = linkonce_odr constant i32 3 +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5_ } +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7_ = linkonce_odr constant i32 4 +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7_ } +// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE_ = linkonce_odr global %"struct.VariableTemplateWithPack::S" { {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6_ } +// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE_ +namespace VariableTemplateWithPack { + struct A { + const int &r; + }; + struct S { + A &&a, &&b, &&c, &&d; + }; + template <int... N> + S &&s = {A{N}...}; + S *p = &s<1, 2, 3, 4>; +} + // CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b // CHECK: define -// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE -// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE, {{.*}} @_ZN21ModifyStaticTemporary1cE +// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE_ +// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE_, {{.*}} @_ZN21ModifyStaticTemporary1cE // CHECK: add // CHECK: store // CHECK: load {{.*}} @_ZN21ModifyStaticTemporary1bE diff --git a/test/CodeGenCXX/constructor-attr.cpp b/test/CodeGenCXX/constructor-attr.cpp index 4f6d635e95d1e..468ce36688f79 100644 --- a/test/CodeGenCXX/constructor-attr.cpp +++ b/test/CodeGenCXX/constructor-attr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // CHECK: @llvm.global_ctors diff --git a/test/CodeGenCXX/constructor-conversion.cpp b/test/CodeGenCXX/constructor-conversion.cpp index ebb414da960bb..bace54fc596df 100644 --- a/test/CodeGenCXX/constructor-conversion.cpp +++ b/test/CodeGenCXX/constructor-conversion.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -46,10 +45,6 @@ int main() { g(3); // g(X(3)) } -// CHECK-LP64: callq __ZN1XC1Ei -// CHECK-LP64: callq __ZN1XC1EPKci -// CHECK-LP64: callq __ZN1XC1Ev - -// CHECK-LP32: calll L__ZN1XC1Ei -// CHECK-LP32: calll L__ZN1XC1EPKci -// CHECK-LP32: calll L__ZN1XC1Ev +// CHECK: call void @_ZN1XC1Ei +// CHECK: call void @_ZN1XC1EPKci +// CHECK: call void @_ZN1XC1Ev diff --git a/test/CodeGenCXX/constructor-default-arg.cpp b/test/CodeGenCXX/constructor-default-arg.cpp index c2cf44ce810c0..98a586494dd0b 100644 --- a/test/CodeGenCXX/constructor-default-arg.cpp +++ b/test/CodeGenCXX/constructor-default-arg.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -31,10 +30,6 @@ int main() { X d(a, 5, 6); } -// CHECK-LP64: callq __ZN1XC1ERKS_iii -// CHECK-LP64: callq __ZN1XC1ERKS_iii -// CHECK-LP64: callq __ZN1XC1ERKS_iii - -// CHECK-LP32: calll L__ZN1XC1ERKS_iii -// CHECK-LP32: calll L__ZN1XC1ERKS_iii -// CHECK-LP32: calll L__ZN1XC1ERKS_iii +// CHECK: call void @_ZN1XC1ERKS_iii +// CHECK: call void @_ZN1XC1ERKS_iii +// CHECK: call void @_ZN1XC1ERKS_iii diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp index ea2ea45a3273e..ce6ddd29f6446 100644 --- a/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -1,6 +1,7 @@ //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s -//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s -//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -cxx-abi microsoft -fno-rtti | FileCheck --check-prefix=CHECKMS %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios6.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios5.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKIOS5 %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti | FileCheck --check-prefix=CHECKMS %s // FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32 // Make sure we attach the 'returned' attribute to the 'this' parameter of @@ -27,15 +28,20 @@ private: B::B(int *i) : i_(i) { } B::~B() { } -// CHECKGEN-LABEL: define void @_ZN1BC1EPi(%class.B* %this, i32* %i) // CHECKGEN-LABEL: define void @_ZN1BC2EPi(%class.B* %this, i32* %i) -// CHECKGEN-LABEL: define void @_ZN1BD1Ev(%class.B* %this) +// CHECKGEN-LABEL: define void @_ZN1BC1EPi(%class.B* %this, i32* %i) // CHECKGEN-LABEL: define void @_ZN1BD2Ev(%class.B* %this) +// CHECKGEN-LABEL: define void @_ZN1BD1Ev(%class.B* %this) -// CHECKARM-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32* %i) // CHECKARM-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* returned %this, i32* %i) -// CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this) +// CHECKARM-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32* %i) // CHECKARM-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* returned %this) +// CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this) + +// CHECKIOS5-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* %this, i32* %i) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* %this, i32* %i) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this) +// CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@QAE@XZ"(%class.B* %this) @@ -51,17 +57,23 @@ private: C::C(int *i, char *c) : B(i), c_(c) { } C::~C() { } -// CHECKGEN-LABEL: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) // CHECKGEN-LABEL: define void @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) -// CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %this) -// CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this) +// CHECKGEN-LABEL: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) // CHECKGEN-LABEL: define void @_ZN1CD2Ev(%class.C* %this) +// CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this) +// CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %this) -// CHECKARM-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c) // CHECKARM-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this, i32* %i, i8* %c) -// CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this) -// CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this) +// CHECKARM-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c) // CHECKARM-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* returned %this) +// CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this) +// CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this) + +// CHECKIOS5-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* %this) +// CHECKIOS5-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* %this) +// CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this) @@ -75,15 +87,20 @@ public: D::D() { } D::~D() { } -// CHECKGEN-LABEL: define void @_ZN1DC1Ev(%class.D* %this) // CHECKGEN-LABEL: define void @_ZN1DC2Ev(%class.D* %this, i8** %vtt) -// CHECKGEN-LABEL: define void @_ZN1DD1Ev(%class.D* %this) +// CHECKGEN-LABEL: define void @_ZN1DC1Ev(%class.D* %this) // CHECKGEN-LABEL: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt) +// CHECKGEN-LABEL: define void @_ZN1DD1Ev(%class.D* %this) -// CHECKARM-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* returned %this) // CHECKARM-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* returned %this, i8** %vtt) -// CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this) +// CHECKARM-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* returned %this) // CHECKARM-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt) +// CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this) + +// CHECKIOS5-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* %this, i8** %vtt) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* %this) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt) +// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@QAE@XZ"(%class.D* %this) diff --git a/test/CodeGenCXX/constructor-direct-call.cpp b/test/CodeGenCXX/constructor-direct-call.cpp index 75e6f216ca519..9567d0968dae4 100644 --- a/test/CodeGenCXX/constructor-direct-call.cpp +++ b/test/CodeGenCXX/constructor-direct-call.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s class Test1 { public: @@ -22,10 +22,10 @@ public: void f2() { // CHECK: %var = alloca %class.Test2, align 4 - // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var) + // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test2C1Ev(%class.Test2* %var) Test2 var; - // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var) + // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test2C1Ev(%class.Test2* %var) var.Test2::Test2(); // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 8, i32 4, i1 false) @@ -45,16 +45,15 @@ public: }; void f3() { - // CHECK: call void @_ZN5Test3C1Ev(%class.Test3* %var) + // CHECK: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var) Test3 var; - // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var2) + // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var2) Test3 var2; - // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var) + // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var) var.Test3::Test3(); - // CHECK-NEXT: call void @_ZN5Test3C1ERKS_(%class.Test3* %var, %class.Test3* %var2) + // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1ERKS_(%class.Test3* %var, %class.Test3* dereferenceable({{[0-9]+}}) %var2) var.Test3::Test3(var2); } - diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp index 7842d9c725e53..8ea7eacd2b2bd 100644 --- a/test/CodeGenCXX/constructor-for-array-members.cpp +++ b/test/CodeGenCXX/constructor-for-array-members.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -39,6 +38,4 @@ int main() { m1.pr(); } -// CHECK-LP64: callq __ZN1SC1Ev - -// CHECK-LP32: calll L__ZN1SC1Ev +// CHECK: call void @_ZN1SC1Ev diff --git a/test/CodeGenCXX/constructor-init-reference.cpp b/test/CodeGenCXX/constructor-init-reference.cpp index 5e75159765188..61f426da51fdd 100644 --- a/test/CodeGenCXX/constructor-init-reference.cpp +++ b/test/CodeGenCXX/constructor-init-reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | grep "store i32\* @x, i32\*\*" +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s int x; struct A { @@ -6,4 +6,4 @@ struct A { A() : y(x) {} }; A z; - +// CHECK: store i32* @x, i32** diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index 477a439f337a2..a8f483e53ab5b 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -163,7 +163,7 @@ template<typename T> struct X; // Make sure that the instantiated constructor initializes start and // end properly. -// CHECK-LABEL: define linkonce_odr void @_ZN1XIiEC2ERKS0_(%struct.X* %this, %struct.X* %other) unnamed_addr +// CHECK-LABEL: define linkonce_odr void @_ZN1XIiEC2ERKS0_(%struct.X* %this, %struct.X* dereferenceable({{[0-9]+}}) %other) unnamed_addr // CHECK: {{store.*null}} // CHECK: {{store.*null}} // CHECK: ret diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp index 0d38d10c13822..675e3cfc0a41e 100644 --- a/test/CodeGenCXX/constructor-template.cpp +++ b/test/CodeGenCXX/constructor-template.cpp @@ -1,4 +1,4 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target +// REQUIRES: x86-registered-target // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s // RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s // RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index f730b9ef491a9..b99c5a194157b 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -21,20 +21,19 @@ struct A { A::A(struct Undeclared &ref) : mem(0) {} // Check that delegation works. -// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr -// CHECK: call void @_ZN1AC2ER10Undeclared( - -// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr +// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( -A::A(ValueClass v) : mem(v.y - v.x) {} +// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// CHECK: call void @_ZN1AC2ER10Undeclared( -// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr -// CHECK: call void @_ZN1AC2E10ValueClass( +A::A(ValueClass v) : mem(v.y - v.x) {} // CHECK-LABEL: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( +// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr +// CHECK: call void @_ZN1AC2E10ValueClass( /* Test that things work for inheritance. */ struct B : A { @@ -44,13 +43,12 @@ struct B : A { B::B(struct Undeclared &ref) : A(ref), mem(1) {} -// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr -// CHECK: call void @_ZN1BC2ER10Undeclared( - -// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr +// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( // CHECK: call void @_ZN6MemberC1Ei( +// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// CHECK: call void @_ZN1BC2ER10Undeclared( /* Test that the delegation optimization is disabled for classes with @@ -64,15 +62,14 @@ struct C : virtual A { }; C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {} +// CHECK-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr +// CHECK: call void @_ZN6MemberC1Ei( + // CHECK-LABEL: define void @_ZN1CC1Ei(%struct.C* %this, i32 %x) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( -// CHECK-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr -// CHECK: call void @_ZN6MemberC1Ei( - - /* Test that the delegation optimization is disabled for varargs constructors. */ @@ -83,17 +80,16 @@ struct D : A { D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {} -// CHECK-LABEL: define void @_ZN1DC1Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr +// CHECK-LABEL: define void @_ZN1DC2Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( -// CHECK-LABEL: define void @_ZN1DC2Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr +// CHECK-LABEL: define void @_ZN1DC1Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( - // PR6622: this shouldn't crash namespace test0 { struct A {}; diff --git a/test/CodeGenCXX/convert-to-fptr.cpp b/test/CodeGenCXX/convert-to-fptr.cpp index e497acf33dc44..c3be9627ba731 100644 --- a/test/CodeGenCXX/convert-to-fptr.cpp +++ b/test/CodeGenCXX/convert-to-fptr.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -39,9 +38,5 @@ int main() return 0; } -// CHECK-LP64: callq __ZN1AcvPFiiEEv -// CHECK-LP64: callq __ZN1BcvRFiiEEv - -// CHECK-LP32: calll L__ZN1AcvPFiiEEv -// CHECK-LP32: calll L__ZN1BcvRFiiEEv - +// CHECK: call i32 (i32)* (%struct.A*)* @_ZN1AcvPFiiEEv +// CHECK: call i32 (i32)* (%struct.B*)* @_ZN1BcvRFiiEEv diff --git a/test/CodeGenCXX/copy-assign-synthesis-1.cpp b/test/CodeGenCXX/copy-assign-synthesis-1.cpp index 2ffc7bcb7c8d2..5813d9c92d804 100644 --- a/test/CodeGenCXX/copy-assign-synthesis-1.cpp +++ b/test/CodeGenCXX/copy-assign-synthesis-1.cpp @@ -1,4 +1,3 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ // RUN: FileCheck %s // RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ @@ -93,5 +92,4 @@ int main() { dstY.pr(); } -// CHECK: define linkonce_odr %struct.X* @_ZN1XaSERKS_ - +// CHECK: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.X* @_ZN1XaSERKS_ diff --git a/test/CodeGenCXX/copy-assign-synthesis-2.cpp b/test/CodeGenCXX/copy-assign-synthesis-2.cpp index 18e92f98ebdef..0bc7d3d6529fb 100644 --- a/test/CodeGenCXX/copy-assign-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-assign-synthesis-2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s struct A {}; A& (A::*x)(const A&) = &A::operator=; -// CHECK-LABEL: define linkonce_odr %struct.A* @_ZN1AaSERKS_ +// CHECK-LABEL: define linkonce_odr {{.*}}%struct.A* @_ZN1AaSERKS_ diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp index 727af1ba7cd3d..c263b7ebf9524 100644 --- a/test/CodeGenCXX/copy-constructor-elim-2.cpp +++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp @@ -21,7 +21,7 @@ namespace no_elide_base { Derived(const Other &O); }; - // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* %O) unnamed_addr + // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* dereferenceable({{[0-9]+}}) %O) unnamed_addr Derived::Derived(const Other &O) // CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv // CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_ @@ -74,4 +74,3 @@ namespace PR12139 { return a.value; } } - diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp index ad3a87b9d5f88..8e9bee973771f 100644 --- a/test/CodeGenCXX/copy-constructor-elim.cpp +++ b/test/CodeGenCXX/copy-constructor-elim.cpp @@ -1,6 +1,9 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: not grep "_ZN1CC1ERK1C" %t -// RUN: not grep "_ZN1SC1ERK1S" %t +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix MS +// CHECK-NOT: _ZN1CC1ERK1C +// CHECK-NOT: _ZN1SC1ERK1S +// MS-NOT: ?0C@@QAE@ABV0 +// MS-NOT: ?0S@@QAE@ABV0 extern "C" int printf(...); diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 03c66339947d7..4bb0fee25e518 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s struct A { virtual void a(); }; A x(A& y) { return y; } -// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A*) unnamed_addr +// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A* dereferenceable({{[0-9]+}})) unnamed_addr // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index c8b265ca2d123..47f8e131d62e5 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -21,7 +21,7 @@ struct P { }; -// CHECK-LABEL: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X*) unnamed_addr +// CHECK-LABEL: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X* dereferenceable({{[0-9]+}})) unnamed_addr struct X : M, N, P { // ... X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd), au_i1(1234), au1_4("MASKED") {} @@ -136,15 +136,13 @@ void f(B b1) { B b2 = b1; } -// CHECK: define linkonce_odr [[A:%.*]]* @_ZN12rdar138169401AaSERKS0_( +// CHECK: define linkonce_odr dereferenceable({{[0-9]+}}) [[A:%.*]]* @_ZN12rdar138169401AaSERKS0_( // CHECK: [[THIS:%.*]] = load [[A]]** // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1 -// CHECK-NEXT: [[T1:%.*]] = bitcast [2 x i8]* [[T0]] to i16* // CHECK-NEXT: [[OTHER:%.*]] = load [[A]]** // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1 -// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8]* [[T2]] to i16* -// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T1]] to i8* -// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T3]] to i8* +// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T0]] to i8* +// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] to i8* // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false) // CHECK-NEXT: ret [[A]]* [[THIS]] @@ -153,16 +151,14 @@ void f(B b1) { // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i8*** // CHECK-NEXT: store i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2), i8*** [[T0]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1 -// CHECK-NEXT: [[T1:%.*]] = bitcast [2 x i8]* [[T0]] to i16* // CHECK-NEXT: [[OTHER:%.*]] = load [[A]]** // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1 -// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8]* [[T2]] to i16* -// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T1]] to i8* -// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T3]] to i8* +// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T0]] to i8* +// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] to i8* // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false) // CHECK-NEXT: ret void -// CHECK-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"*) unnamed_addr +// CHECK-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"* dereferenceable({{[0-9]+}})) unnamed_addr // CHECK: call void @_ZN6PR66281TC1Ev // CHECK: call void @_ZN6PR66281TC1Ev // CHECK: call void @_ZN6PR66281AC2ERKS0_RKNS_1TES5_ diff --git a/test/CodeGenCXX/coverage.cpp b/test/CodeGenCXX/coverage.cpp index 1f1611bd8fcd9..88f74098efa87 100644 --- a/test/CodeGenCXX/coverage.cpp +++ b/test/CodeGenCXX/coverage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -test-coverage -femit-coverage-notes | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - -test-coverage -femit-coverage-notes | FileCheck %s extern "C" void test_name1() {} void test_name2() {} diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index d8d1fab7cef34..d869a2bfd5d9c 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s -// RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \ +// RUN: %clang_cc1 -triple x86_64--netbsd -emit-llvm \ // RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s namespace test1 { @@ -61,7 +61,7 @@ namespace test4 { // test that we don't do this optimization at -O0 so that the debugger can // see both destructors. // NOOPT-DAG: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev - // NOOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev + // NOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev struct A { virtual ~A() {} }; diff --git a/test/CodeGenCXX/cxx0x-defaulted-templates.cpp b/test/CodeGenCXX/cxx0x-defaulted-templates.cpp index f4d5ccc0e3319..6f4c53331d4d8 100644 --- a/test/CodeGenCXX/cxx0x-defaulted-templates.cpp +++ b/test/CodeGenCXX/cxx0x-defaulted-templates.cpp @@ -1,16 +1,16 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s template <typename T> struct X { X(); }; -// CHECK: define {{.*}} @_ZN1XIbEC1Ev // CHECK: define {{.*}} @_ZN1XIbEC2Ev +// CHECK: define {{.*}} @_ZN1XIbEC1Ev template <> X<bool>::X() = default; -// CHECK: define weak_odr {{.*}} @_ZN1XIiEC1Ev // CHECK: define weak_odr {{.*}} @_ZN1XIiEC2Ev +// CHECK: define weak_odr {{.*}} @_ZN1XIiEC1Ev template <typename T> X<T>::X() = default; template X<int>::X(); diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp index c48e61fd14e03..dcc055696e4dd 100644 --- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp +++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp @@ -26,28 +26,30 @@ delegator::delegator() { delegator::delegator(bool) {} -// CHECK: define {{.*}} @_ZN9delegatorC1Ec -// CHECK: {{.*}} @_ZN9delegatorC1Eb -// CHECK: void @__cxa_throw -// CHECK: void @__clang_call_terminate -// CHECK: {{.*}} @_ZN9delegatorD1Ev -// CHECK: define {{.*}} @_ZN9delegatorC2Ec +// CHECK-LABEL: define {{.*}} @_ZN9delegatorC2Ec // CHECK: {{.*}} @_ZN9delegatorC2Eb // CHECK: void @__cxa_throw // CHECK: void @__clang_call_terminate // CHECK: {{.*}} @_ZN9delegatorD2Ev + +// CHECK-LABEL: define {{.*}} @_ZN9delegatorC1Ec +// CHECK: {{.*}} @_ZN9delegatorC1Eb +// CHECK: void @__cxa_throw +// CHECK: void @__clang_call_terminate +// CHECK: {{.*}} @_ZN9delegatorD1Ev delegator::delegator(char) : delegator(true) { throw 0; } -// CHECK: define {{.*}} @_ZN9delegatorC1Ei -// CHECK: {{.*}} @_ZN9delegatorC1Ev +// CHECK-LABEL: define {{.*}} @_ZN9delegatorC2Ei +// CHECK: {{.*}} @_ZN9delegatorC2Ev // CHECK-NOT: void @_ZSt9terminatev // CHECK: ret // CHECK-NOT: void @_ZSt9terminatev -// CHECK: define {{.*}} @_ZN9delegatorC2Ei -// CHECK: {{.*}} @_ZN9delegatorC2Ev + +// CHECK-LABEL: define {{.*}} @_ZN9delegatorC1Ei +// CHECK: {{.*}} @_ZN9delegatorC1Ev // CHECK-NOT: void @_ZSt9terminatev // CHECK: ret // CHECK-NOT: void @_ZSt9terminatev diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp index 091d7b70117ce..91e913e8ea567 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp @@ -55,78 +55,78 @@ std::initializer_list<std::initializer_list<int>> nested = { {1, a}, {3, b}, {5, c} }; -// CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4 -// CHECK-STATIC-BL: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4 -// CHECK-STATIC-BL: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4 -// CHECK-STATIC-BL: @_ZGR6nested3 = private constant [3 x {{.*}}] [ -// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0), i64 2 }, -// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0), i64 2 }, -// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0), i64 2 } +// CHECK-STATIC-BL: @_ZGR6nested0_ = private constant [2 x i32] [i32 1, i32 2], align 4 +// CHECK-STATIC-BL: @_ZGR6nested1_ = private constant [2 x i32] [i32 3, i32 4], align 4 +// CHECK-STATIC-BL: @_ZGR6nested2_ = private constant [2 x i32] [i32 5, i32 6], align 4 +// CHECK-STATIC-BL: @_ZGR6nested_ = private constant [3 x {{.*}}] [ +// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i32 0, i32 0), i64 2 }, +// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i32 0, i32 0), i64 2 }, +// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i32 0, i32 0), i64 2 } // CHECK-STATIC-BL: ], align 8 -// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), i64 3 }, align 8 +// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i32 0, i32 0), i64 3 }, align 8 // CHECK-DYNAMIC-BL: @nested = global -// CHECK-DYNAMIC-BL: @_ZGR6nested = private global [3 x -// CHECK-DYNAMIC-BL: @_ZGR6nested1 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0) -// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1) -// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0), -// CHECK-DYMAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8 -// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8 -// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0) -// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1) -// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0), -// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8 -// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8 -// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0) -// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1) -// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0), -// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8 -// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8 -// CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0), +// CHECK-DYNAMIC-BL: @_ZGR6nested_ = private global [3 x +// CHECK-DYNAMIC-BL: @_ZGR6nested0_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BL: @_ZGR6nested1_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BL: @_ZGR6nested2_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0) +// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 1) +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0), +// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0, i32 0), align 8 +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0, i32 1), align 8 +// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 0) +// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 1) +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 0), +// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 1, i32 0), align 8 +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 1, i32 1), align 8 +// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 0) +// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 1) +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 0), +// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 2, i32 0), align 8 +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 2, i32 1), align 8 +// CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0), // CHECK-DYNAMIC-BL: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8 // CHECK-DYNAMIC-BL: store i64 3, i64* getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8 -// CHECK-STATIC-BE: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4 -// CHECK-STATIC-BE: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4 -// CHECK-STATIC-BE: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4 -// CHECK-STATIC-BE: @_ZGR6nested3 = private constant [3 x {{.*}}] [ -// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0), -// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested to i8*), i64 8) to i32*) } -// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0), -// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested1 to i8*), i64 8) to i32*) } -// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0), -// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested2 to i8*), i64 8) to i32*) } +// CHECK-STATIC-BE: @_ZGR6nested0_ = private constant [2 x i32] [i32 1, i32 2], align 4 +// CHECK-STATIC-BE: @_ZGR6nested1_ = private constant [2 x i32] [i32 3, i32 4], align 4 +// CHECK-STATIC-BE: @_ZGR6nested2_ = private constant [2 x i32] [i32 5, i32 6], align 4 +// CHECK-STATIC-BE: @_ZGR6nested_ = private constant [3 x {{.*}}] [ +// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i32 0, i32 0), +// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested0_ to i8*), i64 8) to i32*) } +// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i32 0, i32 0), +// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested1_ to i8*), i64 8) to i32*) } +// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i32 0, i32 0), +// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested2_ to i8*), i64 8) to i32*) } // CHECK-STATIC-BE: ], align 8 -// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), -// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested3 to i8*), i64 48) to {{.*}}*) } +// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i32 0, i32 0), +// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested_ to i8*), i64 48) to {{.*}}*) } // CHECK-DYNAMIC-BE: @nested = global -// CHECK-DYNAMIC-BE: @_ZGR6nested = private global [3 x -// CHECK-DYNAMIC-BE: @_ZGR6nested1 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32] zeroinitializer -// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0) -// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1) -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0), -// CHECK-DYMAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8 -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 1, i64 0), -// CHECK-DYMAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8 -// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0) -// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1) -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0), -// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8 -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0), -// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8 -// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0) -// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1) -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0), -// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8 -// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 1, i64 0), -// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8 -// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0), +// CHECK-DYNAMIC-BE: @_ZGR6nested_ = private global [3 x +// CHECK-DYNAMIC-BE: @_ZGR6nested0_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BE: @_ZGR6nested1_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BE: @_ZGR6nested2_ = private global [2 x i32] zeroinitializer +// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0) +// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 1) +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0, i32 0), align 8 +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 1, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0, i32 1), align 8 +// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 0) +// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 1) +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 0, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 1, i32 0), align 8 +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1_, i64 1, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 1, i32 1), align 8 +// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 0) +// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 1) +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 0, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 2, i32 0), align 8 +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2_, i64 1, i64 0), +// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 2, i32 1), align 8 +// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 0, i64 0), // CHECK-DYNAMIC-BE: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8 -// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 1, i64 0), +// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i64 1, i64 0), // CHECK-DYNAMIC-BE: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8 diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp index 8e0d161bc0f4e..5a48346be7583 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp @@ -32,8 +32,8 @@ namespace std { }; } -// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3] -// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, {{[^)]*}}), i32* +// CHECK: @_ZGR15globalInitList1_ = private constant [3 x i32] [i32 1, i32 2, i32 3] +// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1_, {{[^)]*}}), i32* std::initializer_list<int> globalInitList1 = {1, 2, 3}; void fn1(int i) { diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 164cbce027ef4..4d30344e3c8d0 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s namespace std { typedef decltype(sizeof(int)) size_t; @@ -47,8 +47,8 @@ struct wantslist1 { ~wantslist1(); }; -// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3] -// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 } +// CHECK: @_ZGR15globalInitList1_ = private constant [3 x i32] [i32 1, i32 2, i32 3] +// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1_, i32 0, i32 0), i{{32|64}} 3 } std::initializer_list<int> globalInitList1 = {1, 2, 3}; namespace thread_local_global_array { @@ -57,12 +57,12 @@ namespace thread_local_global_array { // objects aren't really a problem). // // CHECK: @_ZN25thread_local_global_array1xE = thread_local global - // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] + // CHECK: @_ZGRN25thread_local_global_array1xE_ = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] std::initializer_list<int> thread_local x = { 1, 2, 3, 4 }; } // CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer -// CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer +// CHECK: @_ZGR15globalInitList2_ = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer // CHECK: @_ZN15partly_constant1kE = global i32 0, align 4 // CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 @@ -77,16 +77,16 @@ namespace thread_local_global_array { // thread_local initializer: // CHECK-LABEL: define internal void -// CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0), +// CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE_, i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8 // CHECK-LABEL: define internal void -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 0 -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 1 +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 0 +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 1 // CHECK: __cxa_atexit -// CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i64 0, i64 0), +// CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i64 0, i64 0), // CHECK: %[[WITHARG]]** getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 0), align 8 // CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 1), align 8 // CHECK: call void @_ZN10destroyme1D1Ev @@ -384,7 +384,7 @@ namespace partly_constant { // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0) - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4_, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. @@ -431,3 +431,37 @@ namespace nested { // CHECK: } } } + +namespace DR1070 { + struct A { + A(std::initializer_list<int>); + }; + struct B { + int i; + A a; + }; + B b = {1}; + struct C { + std::initializer_list<int> a; + B b; + std::initializer_list<double> c; + }; + C c = {}; +} + +namespace ArrayOfInitList { + struct S { + S(std::initializer_list<int>); + }; + S x[1] = {}; +} + +namespace PR20445 { + struct vector { vector(std::initializer_list<int>); }; + struct MyClass { explicit MyClass(const vector &v); }; + template<int x> void f() { new MyClass({42, 43}); } + template void f<0>(); + // CHECK-LABEL: define {{.*}} @_ZN7PR204451fILi0EEEvv( + // CHECK: call void @_ZN7PR204456vectorC1ESt16initializer_listIiE( + // CHECK: call void @_ZN7PR204457MyClassC1ERKNS_6vectorE( +} diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp index 96ea1d7f00edc..3b1516b925361 100644 --- a/test/CodeGenCXX/cxx11-exception-spec.cpp +++ b/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -1,4 +1,5 @@ -// RUN: not %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s +// expected-no-diagnostics void h(); diff --git a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index acc77825ae847..789970b58b53e 100644 --- a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -20,6 +20,25 @@ int &fn2(int &v) { // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8 // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B* %[[INITLIST2:.*]], i32 0, i32 0 // CHECK: store i32* %{{.*}}, i32** %[[R]], align 8 - // CHECK: call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]]) + // CHECK: call dereferenceable({{[0-9]+}}) i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]]) return B{v}.f(); } + +// CHECK: define {{.*}}@__cxx_global_var_init( +// +// CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev( +// CHECK: getelementptr inbounds {{.*}}, i64 1 +// CHECK: br i1 +// +// CHECK: getelementptr inbounds {{.*}}, i64 1 +// CHECK: icmp eq {{.*}}, i64 30 +// CHECK: br i1 +// +// CHECK: call i32 @__cxa_atexit( +namespace NonTrivialInit { + struct A { A(); A(const A&) = delete; ~A(); }; + struct B { A a[20]; }; + // NB, this must be large enough to be worth memsetting for this test to be + // meaningful. + B b[30] = {}; +} diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp index 23577bec661a6..2393939b031d6 100644 --- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp +++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp @@ -28,7 +28,7 @@ void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // { 4, 5, 6 } // -// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1 +// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_0]], i32 1 // // CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_1]], i64 0, i64 0 // CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4) @@ -56,7 +56,6 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // CHECK: store i64 %[[ELTS]], i64* %[[COOKIE]] // CHECK: %[[START_AS_i8:.*]] = getelementptr inbounds i8* %[[ALLOC]], i64 8 // CHECK: %[[START_AS_S:.*]] = bitcast i8* %[[START_AS_i8]] to %[[S]]* -// CHECK: %[[END_AS_S:.*]] = getelementptr inbounds %[[S]]* %[[START_AS_S]], i64 %[[ELTS]] // // Explicit initializers: // @@ -73,7 +72,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // { 4, 5, 6 } // -// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1 +// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_0]], i32 1 // // CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_1]], i64 0, i64 0 // CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4) @@ -82,25 +81,80 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // CHECK: %[[S_1_2:.*]] = getelementptr inbounds %[[S]]* %[[S_1_1]], i64 1 // CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_2]], i32 6) // -// CHECK: %[[S_2:.*]] = getelementptr [3 x %[[S]]]* %[[S_1]], i32 1 +// And the rest. +// +// CHECK: %[[S_2:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_1]], i32 1 // CHECK: %[[S_2_AS_S:.*]] = bitcast [3 x %[[S]]]* %[[S_2]] to %[[S]]* -// CHECK: icmp eq %[[S]]* %[[S_2_AS_S]], %[[END_AS_S]] -// CHECK: br i1 // -// S[n-2][3] initialization loop: +// CHECK: %[[REST:.*]] = sub i64 %[[ELTS]], 6 +// CHECK: icmp eq i64 %[[REST]], 0 +// CHECK: br i1 // -// CHECK: %[[END_INNER:.*]] = getelementptr inbounds %[[S]]* %{{.*}}, i64 3 +// CHECK: %[[END:.*]] = getelementptr inbounds %[[S]]* %[[S_2_AS_S]], i64 %[[REST]] // CHECK: br label // -// S[3] initialization loop: +// CHECK: %[[CUR:.*]] = phi %[[S]]* [ %[[S_2_AS_S]], {{.*}} ], [ %[[NEXT:.*]], {{.*}} ] +// CHECK: call void @_ZN1SC1Ev(%[[S]]* %[[CUR]]) +// CHECK: %[[NEXT]] = getelementptr inbounds %[[S]]* %[[CUR]], i64 1 +// CHECK: icmp eq %[[S]]* %[[NEXT]], %[[END]] +// CHECK: br i1 // -// CHECK: call void @_ZN1SC1Ev(%[[S]]* -// CHECK: %[[NEXT_INNER:.*]] = getelementptr inbounds %[[S]]* %{{.*}}, i64 1 -// CHECK: icmp eq %[[S]]* %[[NEXT_INNER]], %[[END_INNER]] -// CHECK: br i1 +// CHECK: } + +struct T { int a; }; +void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; + +// CHECK-LABEL: define // -// CHECK: %[[NEXT_OUTER:.*]] = getelementptr %[[S]]* %{{.*}}, i32 1 -// CHECK: icmp eq %[[S]]* %[[NEXT_OUTER]], %[[END_AS_S]] -// CHECK: br i1 +// CHECK: load i32* @n +// CHECK: call {{.*}} @llvm.umul.with.overflow.i64(i64 %[[N:.*]], i64 12) +// CHECK: %[[ELTS:.*]] = mul i64 %[[N]], 3 +// +// No cookie. +// CHECK-NOT: @llvm.uadd.with.overflow +// +// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 %{{.*}}) +// +// CHECK: %[[START_AS_T:.*]] = bitcast i8* %[[ALLOC]] to %[[T:.*]]* +// +// Explicit initializers: +// +// { 1, 2, 3 } +// +// CHECK: %[[T_0:.*]] = bitcast %[[T]]* %[[START_AS_T]] to [3 x %[[T]]]* +// +// CHECK: %[[T_0_0:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_0]], i64 0, i64 0 +// CHECK: %[[T_0_0_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_0]], i32 0, i32 0 +// CHECK: store i32 1, i32* %[[T_0_0_0]] +// CHECK: %[[T_0_1:.*]] = getelementptr inbounds %[[T]]* %[[T_0_0]], i64 1 +// CHECK: %[[T_0_1_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_1]], i32 0, i32 0 +// CHECK: store i32 2, i32* %[[T_0_1_0]] +// CHECK: %[[T_0_2:.*]] = getelementptr inbounds %[[T]]* %[[T_0_1]], i64 1 +// CHECK: %[[T_0_2_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_2]], i32 0, i32 0 +// CHECK: store i32 3, i32* %[[T_0_2_0]] +// +// { 4, 5, 6 } +// +// CHECK: %[[T_1:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_0]], i32 1 +// +// CHECK: %[[T_1_0:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_1]], i64 0, i64 0 +// CHECK: %[[T_1_0_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_0]], i32 0, i32 0 +// CHECK: store i32 4, i32* %[[T_1_0_0]] +// CHECK: %[[T_1_1:.*]] = getelementptr inbounds %[[T]]* %[[T_1_0]], i64 1 +// CHECK: %[[T_1_1_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_1]], i32 0, i32 0 +// CHECK: store i32 5, i32* %[[T_1_1_0]] +// CHECK: %[[T_1_2:.*]] = getelementptr inbounds %[[T]]* %[[T_1_1]], i64 1 +// CHECK: %[[T_1_2_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_2]], i32 0, i32 0 +// CHECK: store i32 6, i32* %[[T_1_2_0]] +// +// And the rest gets memset to 0. +// +// CHECK: %[[T_2:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_1]], i32 1 +// CHECK: %[[T_2_AS_T:.*]] = bitcast [3 x %[[T]]]* %[[T_2]] to %[[T]]* +// +// CHECK: %[[SIZE:.*]] = sub i64 %{{.*}}, 24 +// CHECK: %[[REST:.*]] = bitcast %[[T]]* %[[T_2_AS_T]] to i8* +// CHECK: call void @llvm.memset.p0i8.i64(i8* %[[REST]], i8 0, i64 %[[SIZE]], i32 4, i1 false) // // CHECK: } + diff --git a/test/CodeGenCXX/cxx11-noreturn.cpp b/test/CodeGenCXX/cxx11-noreturn.cpp index 31c651d75efcf..b876bb9661bae 100644 --- a/test/CodeGenCXX/cxx11-noreturn.cpp +++ b/test/CodeGenCXX/cxx11-noreturn.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 %s -o - | FileCheck %s int g(); diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp index 7759d41b0f920..4143164d91ca0 100644 --- a/test/CodeGenCXX/cxx11-thread-local-reference.cpp +++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp @@ -10,10 +10,10 @@ thread_local int &r = f(); int &g() { return r; } // CHECK: define {{.*}} @[[R_INIT:.*]]() -// CHECK: call i32* @_Z1fv() +// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z1fv() // CHECK: store i32* %{{.*}}, i32** @r, align 8 -// CHECK-LABEL: define i32* @_Z1gv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z1gv() // CHECK: call i32* @_ZTW1r() // CHECK: ret i32* %{{.*}} diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 509562dd8fc1a..a3690b352989e 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -21,7 +21,7 @@ template<typename T> thread_local int V<T>::m = g(); // CHECK: @e = global i32 0 int e = V<int>::m; -// CHECK: @_ZN1VIiE1mE = weak_odr thread_local global i32 0 +// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0 // CHECK: @_ZZ1fvE1n = internal thread_local global i32 0 @@ -35,9 +35,9 @@ int e = V<int>::m; // CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global // CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 -// CHECK: @_ZGRZ8tls_dtorvE1u = private thread_local global +// CHECK: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global -// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0 +// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0 // CHECK: @__tls_guard = internal thread_local global i8 0 @@ -46,7 +46,7 @@ int e = V<int>::m; // CHECK: @_ZTH1a = alias void ()* @__tls_init // CHECK: @_ZTHL1d = alias internal void ()* @__tls_init // CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init -// CHECK: @_ZTHN1VIiE1mE = alias weak_odr void ()* @__tls_init +// CHECK: @_ZTHN1VIiE1mE = alias linkonce_odr void ()* @__tls_init // Individual variable initialization functions: @@ -120,8 +120,8 @@ void tls_dtor() { static thread_local T t; // CHECK: load i8* @_ZGVZ8tls_dtorvE1u - // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u) - // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u{{.*}} @__dso_handle + // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u_) + // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1u static thread_local const S &u = S(); } @@ -135,6 +135,24 @@ int PR15991() { return l(); } +struct PR19254 { + static thread_local int n; + int f(); +}; +// CHECK: define {{.*}} @_ZN7PR192541fEv( +int PR19254::f() { + // CHECK: call void @_ZTHN7PR192541nE( + return this->n; +} + +namespace { +thread_local int anon_i{1}; +} +void set_anon_i() { + anon_i = 2; +} +// CHECK-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() + // CHECK: define {{.*}} @[[V_M_INIT:.*]]() // CHECK: load i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) // CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 @@ -171,7 +189,7 @@ int PR15991() { // CHECK: declare extern_weak void @_ZTH1b() -// CHECK-LABEL: define internal hidden i32* @_ZTWL1d() +// CHECK-LABEL: define internal i32* @_ZTWL1d() // CHECK: call void @_ZTHL1d() // CHECK: ret i32* @_ZL1d diff --git a/test/CodeGenCXX/cxx11-unrestricted-union.cpp b/test/CodeGenCXX/cxx11-unrestricted-union.cpp index 0397775b7e3c7..2f22ad2f964a5 100644 --- a/test/CodeGenCXX/cxx11-unrestricted-union.cpp +++ b/test/CodeGenCXX/cxx11-unrestricted-union.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -emit-llvm %s -o - | FileCheck %s struct A { A(); A(const A&); A(A&&); A &operator=(const A&); A &operator=(A&&); ~A(); diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp index ae49a047f6246..8bdf8633d61e2 100644 --- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp @@ -46,7 +46,7 @@ B z { 1 }; // CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @a, i32 0, i32 2) // CHECK: call i32 @_ZN1A1fEv({{.*}} @a) // CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({{.*}}* @a, i32 0, i32 3) -// CHECK: call void @{{.*}}C1Ev({{.*}} getelementptr inbounds (%struct.A* @a, i32 0, i32 4)) +// CHECK: store double 1.000000e+00, double* getelementptr inbounds ({{.*}} @a, i32 0, i32 4, i32 0) // No dynamic initialization of 'b': diff --git a/test/CodeGenCXX/cxx1y-variable-template.cpp b/test/CodeGenCXX/cxx1y-variable-template.cpp index d1e70603e2800..cd73817d8508e 100644 --- a/test/CodeGenCXX/cxx1y-variable-template.cpp +++ b/test/CodeGenCXX/cxx1y-variable-template.cpp @@ -18,7 +18,7 @@ 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]>; -// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global [123 x i32] zeroinitializer -// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global +// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer +// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global // CHECK: call {{.*}}@_Z8init_arrv diff --git a/test/CodeGenCXX/debug-info-alias.cpp b/test/CodeGenCXX/debug-info-alias.cpp new file mode 100644 index 0000000000000..fb18ac5da0066 --- /dev/null +++ b/test/CodeGenCXX/debug-info-alias.cpp @@ -0,0 +1,37 @@ +// RUN: %clang -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s + +template<typename T> +struct foo { +}; +namespace x { +// splitting these over multiple lines to make sure the right token is used for +// the location +template<typename T> +using +# 42 +bar += foo<T*>; +} + +// CHECK: metadata [[BINT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bi] +// CHECK: [[BINT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<int>] [line 42 +x::bar<int> bi; +// CHECK: metadata [[BFLOAT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bf] +// CHECK: [[BFLOAT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<float>] [line 42 +x::bar<float> bf; + +using +// CHECK: metadata [[NARF:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [n] +# 142 +narf // CHECK: [[NARF]] = {{.*}} ; [ DW_TAG_typedef ] [narf] [line 142 += int; +narf n; + +template <typename T> +using tv = void; +// CHECK: null} ; [ DW_TAG_typedef ] [tv<int>] {{.*}} [from ] +tv<int> *tvp; + +using v = void; +// CHECK: null} ; [ DW_TAG_typedef ] [v] {{.*}} [from ] +v *vp; diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp new file mode 100644 index 0000000000000..396b7e94a8ea6 --- /dev/null +++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -emit-llvm -gdwarf-4 -triple x86_64-linux-gnu %s -o - | FileCheck %s + +// Make sure that we emit a global variable for each of the members of the +// anonymous union. + +static union { + int c; + int d; + union { + int a; + }; + struct { + int b; + }; +}; + +int test_it() { + c = 1; + d = 2; + a = 4; + return (c == 1); +} + +// CHECK: [[FILE:.*]] = {{.*}}[ DW_TAG_file_type ] [{{.*}}debug-info-anon-union-vars.cpp] +// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [c] [line 6] [local] [def] +// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [d] [line 6] [local] [def] +// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [a] [line 6] [local] [def] +// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [b] [line 6] [local] [def] diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp index e6317fc2de0ef..5b0850b9643cc 100644 --- a/test/CodeGenCXX/debug-info-byval.cpp +++ b/test/CodeGenCXX/debug-info-byval.cpp @@ -1,4 +1,5 @@ -// RUN: %clang -g -S %s -o - | FileCheck %s +// FIXME: Check IR rather than asm, then triple is not needed. +// RUN: %clang -Xclang -triple=%itanium_abi_triple -g -S %s -o - | FileCheck %s // Test to check presence of debug info for byval parameter. // Radar 8350436. class DAG { diff --git a/test/CodeGenCXX/debug-info-char16.cpp b/test/CodeGenCXX/debug-info-char16.cpp index 06a05b31dd1c3..e6e2f1521bd73 100644 --- a/test/CodeGenCXX/debug-info-char16.cpp +++ b/test/CodeGenCXX/debug-info-char16.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o -| FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o -| FileCheck %s // 16 is DW_ATE_UTF (0x10) encoding attribute. char16_t char_a = u'h'; diff --git a/test/CodeGenCXX/debug-info-class-limited-plugin.test b/test/CodeGenCXX/debug-info-class-limited-plugin.test new file mode 100644 index 0000000000000..61d258d9ffc49 --- /dev/null +++ b/test/CodeGenCXX/debug-info-class-limited-plugin.test @@ -0,0 +1,2 @@ +RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp +REQUIRES: plugins, examples diff --git a/test/CodeGenCXX/debug-info-class-limited.test b/test/CodeGenCXX/debug-info-class-limited.test new file mode 100644 index 0000000000000..0b10728f3c979 --- /dev/null +++ b/test/CodeGenCXX/debug-info-class-limited.test @@ -0,0 +1 @@ +RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g %S/Inputs/debug-info-class-limited.cpp -o - | FileCheck %S/Inputs/debug-info-class-limited.cpp diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp index ce72bd347cab5..7a6ee4d441a95 100644 --- a/test/CodeGenCXX/debug-info-class-nolimit.cpp +++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unk-unk -fno-limit-debug-info -o - -emit-llvm -g %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unk-unk -fstandalone-debug -o - -emit-llvm -g %s | FileCheck %s +// On Darwin, this should be the default: +// RUN: %clang_cc1 -triple x86_64-apple-darwin -o - -emit-llvm -g %s | FileCheck %s namespace rdar14101097_1 { // see also PR16214 // Check that we emit debug info for the definition of a struct if the diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp index e1402c96f0432..34add0432c49a 100644 --- a/test/CodeGenCXX/debug-info-class.cpp +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -102,13 +102,9 @@ int main(int argc, char **argv) { // CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int] // CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C] -// CHECK: metadata [[D_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl] -// CHECK: [[D_MEM]] = metadata !{metadata [[D_FUNC:![0-9]*]]} -// CHECK: [[D_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func] +// CHECK: null, i32 0, null, null, metadata !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl] // CHECK: null, i32 0, null, null, metadata !"_ZTS1E"} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl] -// CHECK: [[F:![0-9]*]] = {{.*}} metadata [[F_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl] -// CHECK: [[F_MEM]] = metadata !{metadata [[F_I:![0-9]*]]} -// CHECK: [[F_I]] = {{.*}} ; [ DW_TAG_member ] [i] +// CHECK: [[F:![0-9]*]] = {{.*}} null, i32 0, null, null, metadata !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl] // CHECK: null, i32 0, null, null, metadata !"_ZTS1G"} ; [ DW_TAG_structure_type ] [G] {{.*}} [decl] // CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN1G5innerE"} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def] @@ -118,8 +114,13 @@ int main(int argc, char **argv) { // CHECK: ; [ DW_TAG_structure_type ] [A] // CHECK: HdrSize // CHECK: ; [ DW_TAG_structure_type ] [I] {{.*}} [def] +// +// CHECK: metadata !"_ZTS1D", {{.*}}, metadata [[D_FUNC_DECL:![0-9]*]], metadata {{![0-9]*}}, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[D_FUNC_DECL]] = {{.*}}, metadata !"_ZTS1D", {{.*}}, i32 0, null, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [func] -// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I]]} ; [ DW_TAG_variable ] [i] +// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i] + +// CHECK: [[F_I]] = {{.*}}, metadata !"_ZTS1F", {{.*}} ; [ DW_TAG_member ] [i] // CHECK: ![[EXCEPTLOC]] = metadata !{i32 84, // CHECK: ![[RETLOC]] = metadata !{i32 83, diff --git a/test/CodeGenCXX/debug-info-ctor2.cpp b/test/CodeGenCXX/debug-info-ctor2.cpp index 19bd64b3cdada..3bc931e984487 100644 --- a/test/CodeGenCXX/debug-info-ctor2.cpp +++ b/test/CodeGenCXX/debug-info-ctor2.cpp @@ -1,4 +1,5 @@ -// RUN: %clang -fverbose-asm -g -S %s -o - | grep AT_explicit +// FIXME: Check IR rather than asm, then triple is not needed. +// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit class MyClass diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp index 04fe7a03e1685..1b9a055527d00 100644 --- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp +++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fno-limit-debug-info %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fstandalone-debug %s -o - | FileCheck %s class Test { diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index 0f4b09afb5ddf..f0b97ccd2c8e1 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -12,7 +12,6 @@ D d; // CHECK: ; [ DW_TAG_enumeration_type ] [A] [line 3, size 32, align 32, offset 0] [def] [from int] // CHECK: ; [ DW_TAG_enumeration_type ] [B] [line 4, size 64, align 64, offset 0] [def] [from long unsigned int] // CHECK: ; [ DW_TAG_enumeration_type ] [C] [line 5, size 32, align 32, offset 0] [def] [from ] -// CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [decl] [from ] namespace PR14029 { // Make sure this doesn't crash/assert. @@ -27,3 +26,54 @@ namespace PR14029 { }; Test<int> t; } + +namespace test2 { +// FIXME: this should just be a declaration under -fno-standalone-debug +// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST2:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test21EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: [[TEST2]] = {{.*}} ; [ DW_TAG_namespace ] [test2] +// CHECK: [[TEST_ENUMS]] = metadata !{metadata [[TEST_E:![0-9]*]]} +// CHECK: [[TEST_E]] = {{.*}}, metadata !"e", i64 0} ; [ DW_TAG_enumerator ] [e :: 0] +enum E : int; +void func(E *) { +} +enum E : int { e }; +} + +namespace test3 { +// FIXME: this should just be a declaration under -fno-standalone-debug +// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST3:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test31EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: [[TEST3]] = {{.*}} ; [ DW_TAG_namespace ] [test3] +enum E : int { e }; +void func(E *) { +} +} + +namespace test4 { +// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST4:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test41EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: [[TEST4]] = {{.*}} ; [ DW_TAG_namespace ] [test4] +enum E : int; +void f1(E *) { +} +enum E : int { e }; +void f2(E) { +} +} + +// CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [decl] [from ] + +namespace test5 { +// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST5:![0-9]*]], {{.*}}, null, {{[^,]*}}, null, null, metadata !"_ZTSN5test51EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: [[TEST5]] = {{.*}} ; [ DW_TAG_namespace ] [test5] +enum E : int; +void f1(E *) { +} +} + +namespace test6 { +// Ensure typedef'd enums aren't manifest by debug info generation. +// This could cause "typedef changes linkage of anonymous type, but linkage was +// already computed" errors. +// CHECK-NOT: test7 +typedef enum { +} E; +} diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp index f0e2608db856a..810c3ee7ae9b0 100644 --- a/test/CodeGenCXX/debug-info-enum.cpp +++ b/test/CodeGenCXX/debug-info-enum.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s // CHECK: [[ENUMS:![0-9]*]], {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}} ; [ DW_TAG_compile_unit ] // CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]]} @@ -34,3 +34,12 @@ void func() { e x; } } + +namespace test4 { +// Don't try to build debug info for a dependent enum. +// CHECK-NOT: test4 +template <typename T> +struct S { + enum e { E = T::v }; +}; +} diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp index 4ca1c8d1eced2..e65d3289f8b1a 100644 --- a/test/CodeGenCXX/debug-info-function-context.cpp +++ b/test/CodeGenCXX/debug-info-function-context.cpp @@ -29,8 +29,8 @@ int global_namespace_variable = 1; // CHECK: metadata !"_ZTS1C", metadata !"static_member_function"{{.*}} [ DW_TAG_subprogram ] [line 13] [def] [static_member_function] -// CHECK: metadata !22, metadata !"global_function"{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function] -// CHECK: !22 = {{.*}} [ DW_TAG_file_type ] +// CHECK: metadata [[FILE:![0-9]*]], metadata !"global_function"{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function] +// CHECK: [[FILE]] = {{.*}} [ DW_TAG_file_type ] -// CHECK: metadata !24, metadata !"global_namespace_function"{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function] -// CHECK: !24 = {{.*}} [ DW_TAG_namespace ] [ns] [line 19] +// CHECK: metadata [[NS:![0-9]*]], metadata !"global_namespace_function"{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function] +// CHECK: [[NS]] = {{.*}} [ DW_TAG_namespace ] [ns] [line 19] diff --git a/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/test/CodeGenCXX/debug-info-gline-tables-only.cpp index 7ecdeb2ec22ec..b766c73cc22a4 100644 --- a/test/CodeGenCXX/debug-info-gline-tables-only.cpp +++ b/test/CodeGenCXX/debug-info-gline-tables-only.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -gline-tables-only -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -fno-rtti -gline-tables-only -S -emit-llvm -o - | FileCheck %s // Checks that clang with "-gline-tables-only" doesn't emit debug info // for variables and types. diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp index afa77077a25d4..28b1fab31bc70 100644 --- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -g -fno-use-cxa-atexit -S -emit-llvm -o - \ +// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -S -emit-llvm -o - \ // RUN: | FileCheck %s --check-prefix=CHECK-NOKEXT -// RUN: %clang_cc1 %s -g -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \ +// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \ // RUN: | FileCheck %s --check-prefix=CHECK-KEXT class A { diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp new file mode 100644 index 0000000000000..8dc30c8923166 --- /dev/null +++ b/test/CodeGenCXX/debug-info-global.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s + +// Multiple references to the same constant should result in only one entry in +// the globals list. + +namespace ns { +const int cnst = 42; +} +int f1() { + return ns::cnst + ns::cnst; +} + +// CHECK: metadata [[GLOBALS:![0-9]*]], metadata {{![0-9]*}}, metadata !"{{.*}}", i32 {{[0-9]*}}} ; [ DW_TAG_compile_unit ] + +// CHECK: [[GLOBALS]] = metadata !{metadata [[CNST:![0-9]*]]} + +// CHECK: [[CNST]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"cnst", {{.*}}; [ DW_TAG_variable ] [cnst] +// CHECK: [[NS]] = {{.*}}; [ DW_TAG_namespace ] [ns] + diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp new file mode 100644 index 0000000000000..131cebae48757 --- /dev/null +++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// +// Test that indirect field decls are handled gracefully. +// rdar://problem/16348575 +// +template <class T, int T::*ptr> class Foo { }; + +struct Bar { + int i1; + // CHECK: [ DW_TAG_member ] [line [[@LINE+1]], size 32, align 32, offset 32] [from _ZTSN3BarUt_E] + union { + // CHECK: [ DW_TAG_member ] [i2] [line [[@LINE+1]], size 32, align 32, offset 0] [from int] + int i2; + }; +}; + +Foo<Bar, &Bar::i2> the_foo; diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp index 54a2424fddd9a..294d1f6b6d205 100644 --- a/test/CodeGenCXX/debug-info-limited.cpp +++ b/test/CodeGenCXX/debug-info-limited.cpp @@ -11,8 +11,7 @@ A *foo (A* x) { return a; } -// Verify that we're not emitting a full definition of B in limit debug mode. -// CHECK: ; [ DW_TAG_class_type ] [B] {{.*}} [decl] +// CHECK: ; [ DW_TAG_class_type ] [B] {{.*}} [def] class B { public: diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp new file mode 100644 index 0000000000000..e14090f03f984 --- /dev/null +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// PR19864 +int main() { + int v[] = {13, 21, 8, 3, 34, 1, 5, 2}; + int a = 0, b = 0; + for (int x : v) + if (x >= 3) + ++b; // CHECK: add nsw{{.*}}, 1 + else if (x >= 0) + ++a; // CHECK: add nsw{{.*}}, 1 + // The continuation block if the if statement should not share the + // location of the ++a statement. Having it point to the end of + // the condition is not ideal either, but it's less missleading. + + // CHECK: br label + // CHECK: br label + // CHECK: br label {{.*}}, !dbg ![[DBG:.*]] + // CHECK: ![[DBG]] = metadata !{i32 [[@LINE-11]], i32 0, metadata !{{.*}}, null} + +} diff --git a/test/CodeGenCXX/debug-info-member.cpp b/test/CodeGenCXX/debug-info-member.cpp index 8c2e3ebded4b8..7ba97b5b54e71 100644 --- a/test/CodeGenCXX/debug-info-member.cpp +++ b/test/CodeGenCXX/debug-info-member.cpp @@ -1,4 +1,5 @@ -// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public +// FIXME: Check IR rather than asm, then triple is not needed. +// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public class A { public: int x; diff --git a/test/CodeGenCXX/debug-info-method-spec.cpp b/test/CodeGenCXX/debug-info-method-spec.cpp index 2068c5ce4fad6..c00da004f456e 100644 --- a/test/CodeGenCXX/debug-info-method-spec.cpp +++ b/test/CodeGenCXX/debug-info-method-spec.cpp @@ -1,4 +1,5 @@ -// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_AT_specification +// FIXME: Check IR rather than asm, then triple is not needed. +// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification // Radar 9254491 class A { public: diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index 50b3f66354e09..49b8dc47855de 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o - | FileCheck %s // CHECK: metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] // CHECK: metadata !"_ZN1A3fooEiS_3$_0", {{.*}} [protected] // CHECK: ![[THISTYPE:[0-9]+]] = {{.*}} ; [ DW_TAG_pointer_type ] {{.*}} [artificial] [from _ZTS1A] diff --git a/test/CodeGenCXX/debug-info-method2.cpp b/test/CodeGenCXX/debug-info-method2.cpp index a927c49d307ad..a365312b2584f 100644 --- a/test/CodeGenCXX/debug-info-method2.cpp +++ b/test/CodeGenCXX/debug-info-method2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -flimit-debug-info -x c++ -g -S -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -fno-standalone-debug -x c++ -g -S -emit-llvm < %s | FileCheck %s // rdar://10336845 // Preserve type qualifiers in -flimit-debug-info mode. diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index a2d7ede1643e8..a1284d2d27710 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s -// RUN: %clang -g -fno-limit-debug-info -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s +// RUN: %clang_cc1 -g -fno-standalone-debug -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s +// RUN: %clang_cc1 -g -fstandalone-debug -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s namespace A { #line 1 "foo.cpp" @@ -36,42 +36,48 @@ int func(bool b) { return i + X::B::i + Y::B::i; } +namespace A { +using B::i; +} + // This should work even if 'i' and 'func' were declarations & not definitions, // but it doesn't yet. -// CHECK: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ] -// CHECK: [[FILE:![0-9]*]] {{.*}}debug-info-namespace.cpp" +// CHECK: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 1} ; [ DW_TAG_compile_unit ] // CHECK: [[FOO:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [foo] [line 5, size 0, align 0, offset 0] [decl] [from ] // CHECK: [[FOOCPP:![0-9]*]] = metadata !{metadata !"foo.cpp", {{.*}} // CHECK: [[NS:![0-9]*]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1] -// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 5] +// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE:![0-9]*]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 5] +// CHECK: [[FILE]] {{.*}}debug-info-namespace.cpp" // CHECK: [[BAR:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [decl] [from ] // CHECK: [[F1:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 4] [def] [f1] // CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] // CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp] // CHECK: [[I:![0-9]*]] = {{.*}}, metadata [[NS]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i] -// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]]} +// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]], metadata [[M13:![0-9]*]]} // CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 11} ; [ DW_TAG_imported_module ] // CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ] -// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 15, metadata !"E"} ; [ DW_TAG_imported_module ] +// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 15, metadata !"E"} ; [ DW_TAG_imported_declaration ] // CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX2:![0-9]*]], metadata [[NS]], i32 19} ; [ DW_TAG_imported_module ] // CHECK: [[LEX2]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[LEX1:![0-9]+]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ] // CHECK: [[LEX1]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ] // CHECK: [[M5]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ] -// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:![0-9]*]], i32 23} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:![0-9]*]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:!"_ZTSN1A1B3fooE"]], i32 23} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:!"_ZTSN1A1B3barE"]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] // CHECK: [[M8]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[F1]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] // CHECK: [[M9]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] // CHECK: [[M10]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAZ:![0-9]*]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] // CHECK: [[BAZ]] = metadata !{i32 {{[0-9]*}}, metadata [[FOOCPP]], metadata [[NS]], {{.*}}, metadata !"_ZTSN1A1B3barE"} ; [ DW_TAG_typedef ] [baz] {{.*}} [from _ZTSN1A1B3barE] -// CHECK: [[M11]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}, metadata !"X"} ; [ DW_TAG_imported_module ] -// CHECK: [[M12]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[M11]], i32 {{[0-9]*}}, metadata !"Y"} ; [ DW_TAG_imported_module ] +// CHECK: [[M11]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}, metadata !"X"} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M12]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[M11]], i32 {{[0-9]*}}, metadata !"Y"} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M13]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] -// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ] -// CHECK-GMLT: [[MODULES]] = metadata !{i32 0} +// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 2} ; [ DW_TAG_compile_unit ] +// CHECK-GMLT: [[MODULES]] = metadata !{} // CHECK-NOLIMIT: ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [def] [from ] // FIXME: It is confused on win32 to generate file entry when dosish filename is given. // REQUIRES: shell // REQUIRES: shell-preserves-root +// REQUIRES: dw2 diff --git a/test/CodeGenCXX/debug-info-pubtypes.cpp b/test/CodeGenCXX/debug-info-pubtypes.cpp deleted file mode 100644 index 6393cddeef67e..0000000000000 --- a/test/CodeGenCXX/debug-info-pubtypes.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fno-limit-debug-info -S -mllvm -generate-dwarf-pub-sections=Enable %s -o - | FileCheck %s - -// FIXME: This testcase shouldn't rely on assembly emission. -//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]] -//CHECK: .asciz "G" -//CHECK-NEXT: .long 0 -//CHECK-NEXT: Lpubtypes_end[[SECNUM]] - -class G { -public: - void foo(); -}; - -void G::foo() { -} diff --git a/test/CodeGenCXX/debug-info-qualifiers.cpp b/test/CodeGenCXX/debug-info-qualifiers.cpp new file mode 100644 index 0000000000000..c6b935f9039a5 --- /dev/null +++ b/test/CodeGenCXX/debug-info-qualifiers.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// Test (r)value and CVR qualifiers on C++11 non-static member functions. +class A { +public: + // CHECK: i32 [[@LINE+2]], metadata ![[PLSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [reference] [l] + // CHECK: ![[PLSR]] ={{.*}}[ DW_TAG_subroutine_type ]{{.*}}[reference] + void l() const &; + // CHECK: ![[ARGS:[0-9]+]] = metadata !{null, metadata ![[THIS:[0-9]+]]} + // CHECK: ![[THIS]] = {{.*}} metadata ![[CONST_A:.*]]} ; [ DW_TAG_pointer_type ] + // CHECK: ![[CONST_A]] = {{.*}} [ DW_TAG_const_type ] + // CHECK: i32 [[@LINE+2]], metadata ![[PRSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [rvalue reference] [r] + // CHECK: ![[PRSR]] ={{.*}}metadata ![[ARGS]], i32 0, null, null, null}{{.*}}[ DW_TAG_subroutine_type ]{{.*}}[rvalue reference] + void r() const &&; +}; + +void g() { + A a; + // The type of pl is "void (A::*)() const &". + // CHECK: metadata ![[PL:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pl] [line [[@LINE+2]]] + // CHECK: metadata ![[PLSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] + auto pl = &A::l; + + // CHECK: metadata ![[PR:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pr] [line [[@LINE+2]]] + // CHECK: metadata ![[PRSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] + auto pr = &A::r; +} diff --git a/test/CodeGenCXX/debug-info-same-line.cpp b/test/CodeGenCXX/debug-info-same-line.cpp index 519e9eeb87a42..965a538f84721 100644 --- a/test/CodeGenCXX/debug-info-same-line.cpp +++ b/test/CodeGenCXX/debug-info-same-line.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -g -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // Make sure that clang outputs distinct debug info for a function // that is inlined twice on the same line. Otherwise it would appear @@ -6,118 +6,59 @@ #define INLINE inline __attribute__((always_inline)) -INLINE int -product (int x, int y) -{ - int result = x * y; - return result; -} - -INLINE int -sum (int a, int b) -{ - int result = a + b; - return result; -} +int i; -int -strange_max (int m, int n) -{ - if (m > n) - return m; - else if (n > m) - return n; - else - return 0; +INLINE void sum(int a, int b) { + i = a + b; } -int -foo (int i, int j) -{ - if (strange_max (i, j) == i) - return product (i, j); - else if (strange_max (i, j) == j) - return sum (i, j); - else - return product (sum (i, i), sum (j, j)); +void noinline(int x, int y) { + i = x + y; } -int -main(int argc, char const *argv[]) -{ - - int array[3]; - int n; +#define CALLS sum(9, 10), sum(11, 12) - array[0] = foo (1238, 78392); - array[1] = foo (379265, 23674); - array[2] = foo (872934, 234); - - n = strange_max(array[0], strange_max(array[1], array[2])); - - return n & 0xf; +inline void inlsum(int t, int u) { + i = t + u; } -// CHECK: define {{.*}} @_Z3fooii -// i -// CHECK: call void @llvm.dbg.declare -// j -// CHECK: call void @llvm.dbg.declare -// x -// CHECK: call void @llvm.dbg.declare -// y -// CHECK: call void @llvm.dbg.declare -// result -// CHECK: call void @llvm.dbg.declare - -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD:[0-9]+]]), !dbg ![[A_DI:[0-9]+]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD:[0-9]+]]), !dbg ![[B_DI:[0-9]+]] -// result -// CHECK: call void @llvm.dbg.declare - -// We want to see a distinct !dbg node. -// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg ![[A_DI]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg !{{.*}} -// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg ![[B_DI]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg !{{.*}} -// result -// CHECK: call void @llvm.dbg.declare - -// We want to see a distinct !dbg node. -// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg ![[A_DI]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg !{{.*}} -// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg ![[B_DI]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg !{{.*}} -// result -// CHECK: call void @llvm.dbg.declare - -// Again: we want to see a distinct !dbg node. -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[X_MD:[0-9]+]]), !dbg ![[X_DI:[0-9]+]] -// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[Y_MD:[0-9]+]]), !dbg ![[Y_DI:[0-9]+]] -// result -// CHECK: call void @llvm.dbg.declare - - -// CHECK: define {{.*}} @main -// CHECK: call {{.*}} @_Z3fooii -// CHECK: call {{.*}} @_Z3fooii -// CHECK: call {{.*}} @_Z3fooii -// CHECK: store -// CHECK: getelementptr -// We want to see the same !dbg node for non-inlined functions. -// Needed for GDB compatibility. -// CHECK: load {{.*}} !dbg ![[DBG:.*]] -// CHECK: load {{.*}} !dbg ![[DBG]] -// CHECK: load {{.*}} !dbg ![[DBG]] -// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]] -// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]] - +int main() { + sum(1, 2), sum(3, 4); + noinline(5, 6), noinline(7, 8); + CALLS; + inlsum(13, 14), inlsum(15, 16); +} -// Verify that product() has its own inlined_at location at column 15. -// CHECK-DAG: ![[A_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [a] -// CHECK-DAG: ![[B_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [b] -// CHECK-DAG: ![[X_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [x] -// CHECK-DAG: ![[Y_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [y] -// CHECK-DAG: ![[X_DI]] = metadata !{i32 {{[0-9]+}}, i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata ![[PRODUCT:[0-9]+]]} -// CHECK-DAG: [[PRODUCT]] = metadata !{i32 {{.*}}, i32 16, metadata !{{.*}}, null} -// CHECK-DAG: ![[Y_DI]] = metadata !{i32 {{[0-9]+}}, i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata ![[PRODUCT]]} +// CHECK-LABEL: @main +// CHECK: = add {{.*}} !dbg [[FIRST_INLINE:![0-9]*]] +// CHECK: = add {{.*}} !dbg [[SECOND_INLINE:![0-9]*]] + +// Check that we don't give column information (and thus end up with distinct +// line entries) for two non-inlined calls on the same line. +// CHECK: call {{.*}}noinline{{.*}}({{i32[ ]?[a-z]*}} 5, {{i32[ ]?[a-z]*}} 6), !dbg [[NOINLINE:![0-9]*]] +// CHECK: call {{.*}}noinline{{.*}}({{i32[ ]?[a-z]*}} 7, {{i32[ ]?[a-z]*}} 8), !dbg [[NOINLINE]] + +// FIXME: These should be separate locations but because the two calls have the +// same line /and/ column, they get coalesced into a single inlined call by +// accident. We need discriminators or some other changes to LLVM to cope with +// this. (this is, unfortunately, an LLVM test disguised as a Clang test - since +// inlining is forced to happen here). It's possible this could be fixed in +// Clang, but I doubt it'll be the right place for the fix. +// CHECK: = add {{.*}} !dbg [[FIRST_MACRO_INLINE:![0-9]*]] +// CHECK: = add {{.*}} !dbg [[FIRST_MACRO_INLINE]] + +// Even if the functions are marked inline but do not get inlined, they +// shouldn't use column information, and thus should be at the same debug +// location. +// CHECK: call {{.*}}inlsum{{.*}}({{i32[ ]?[a-z]*}} 13, {{i32[ ]?[a-z]*}} 14), !dbg [[INL_FIRST:![0-9]*]] +// CHECK: call {{.*}}inlsum{{.*}}({{i32[ ]?[a-z]*}} 15, {{i32[ ]?[a-z]*}} 16), !dbg [[INL_SECOND:![0-9]*]] + +// [[FIRST_INLINE]] = +// [[SECOND_INLINE]] = + +// FIXME: These should be the same location since the functions appear on the +// same line and were not inlined - they needlessly have column information +// intended to disambiguate inlined calls, which is going to confuse GDB as it +// doesn't cope well with column information. +// [[INL_FIRST]] = +// [[INL_SECOND]] = diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp index 557ee31783547..0447dc04d56bb 100644 --- a/test/CodeGenCXX/debug-info-scope.cpp +++ b/test/CodeGenCXX/debug-info-scope.cpp @@ -17,12 +17,12 @@ char *return_char (int input) int main2() { // CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]] -// CHECK metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] if (char *ptr = return_char(1)) { printf ("%s", ptr); } // CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]] -// CHECK metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] +// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] if (char *ptr = return_char(2)) { printf ("%s", ptr); } diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp new file mode 100644 index 0000000000000..506c0d535751c --- /dev/null +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fno-standalone-debug | FileCheck %s + +// Run again with -gline-tables-only and verify we don't crash. We won't output +// type info at all. +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -gline-tables-only | FileCheck %s -check-prefix LINES-ONLY + +// LINES-ONLY-NOT: DW_TAG_structure_type + +template <typename T> +struct a { +}; +extern template class a<int>; +// CHECK-NOT: ; [ DW_TAG_structure_type ] [a<int>] + +template <typename T> +struct b { +}; +extern template class b<int>; +b<int> bi; +// CHECK: ; [ DW_TAG_structure_type ] [b<int>] {{.*}} [def] + +template <typename T> +struct c { + void f() {} +}; +extern template class c<int>; +c<int> ci; +// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl] + +template <typename T> +struct d { + void f(); +}; +extern template class d<int>; +d<int> di; +// CHECK: ; [ DW_TAG_structure_type ] [d<int>] {{.*}} [def] + +template <typename T> +struct e { + void f(); +}; +template <typename T> +void e<T>::f() { +} +extern template class e<int>; +e<int> ei; +// There's no guarantee that the out of line definition will appear before the +// explicit template instantiation definition, so conservatively emit the type +// definition here. +// CHECK: ; [ DW_TAG_structure_type ] [e<int>] {{.*}} [def] + +template <typename T> +struct f { + void g(); +}; +extern template class f<int>; +template <typename T> +void f<T>::g() { +} +f<int> fi; +// CHECK: ; [ DW_TAG_structure_type ] [f<int>] {{.*}} [def] + +template <typename T> +struct g { + void f(); +}; +template <> +void g<int>::f(); +extern template class g<int>; +g<int> gi; +// CHECK: ; [ DW_TAG_structure_type ] [g<int>] {{.*}} [def] + +template <typename T> +struct h { +}; +template class h<int>; +// CHECK: ; [ DW_TAG_structure_type ] [h<int>] {{.*}} [def] + +template <typename T> +struct i { + void f() {} +}; +template<> void i<int>::f(); +extern template class i<int>; +i<int> ii; +// CHECK: ; [ DW_TAG_structure_type ] [i<int>] {{.*}} [def] + +template <typename T1, typename T2 = T1> +struct j { +}; +extern template class j<int>; +j<int> jj; +// CHECK: ; [ DW_TAG_structure_type ] [j<int, int>] diff --git a/test/CodeGenCXX/debug-info-template-fwd.cpp b/test/CodeGenCXX/debug-info-template-fwd.cpp new file mode 100644 index 0000000000000..b2b70730efdfd --- /dev/null +++ b/test/CodeGenCXX/debug-info-template-fwd.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -g -emit-llvm -o - | FileCheck %s +// This test is for a crash when emitting debug info for not-yet-completed +// types. +// Test that we don't actually emit a forward decl for the offending class: +// CHECK: [ DW_TAG_structure_type ] [Derived<int>] {{.*}} [def] +// rdar://problem/15931354 +template <class A> class Derived; + +template <class A> class Base { + static Derived<A> *create(); +}; + +template <class A> struct Derived : Base<A> { +}; + +Base<int> *f; + +// During the instantiation of Derived<int>, Base<int> becomes required to be +// complete - since the declaration has already been emitted (due to 'f', +// above), we immediately try to build debug info for Base<int> which then +// requires the (incomplete definition) of Derived<int> which is problematic. +// +// (if 'f' is not present, the point at which Base<int> becomes required to be +// complete during the instantiation of Derived<int> is a no-op because +// Base<int> was never emitted so we ignore it and carry on until we +// wire up the base class of Derived<int> in the debug info later on) +Derived<int> d; diff --git a/test/CodeGenCXX/debug-info-template-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp index c3e241ecc8067..e1f23ada21edd 100644 --- a/test/CodeGenCXX/debug-info-template-limit.cpp +++ b/test/CodeGenCXX/debug-info-template-limit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -triple %itanium_abi_triple -g %s -o - | FileCheck %s // Check that this pointer type is TC<int> // CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ] diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index 9ac1befc1019d..c9a3d9b9177c8 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -g -fno-standalone-debug -triple x86_64-apple-darwin %s -o - | FileCheck %s struct MyClass { template <int i> int add(int j) { @@ -21,7 +21,7 @@ inline int add3(int x) { // CHECK: [[FOO_FUNC]] = {{.*}}, metadata !"_ZN3foo4funcEN5outerIS_E5innerE", i32 {{[0-9]*}}, metadata [[FOO_FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func] // CHECK: [[FOO_FUNC_TYPE]] = {{.*}}, metadata [[FOO_FUNC_PARAMS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] // CHECK: [[FOO_FUNC_PARAMS]] = metadata !{null, metadata !{{[0-9]*}}, metadata [[OUTER_FOO_INNER:![0-9]*]]} -// CHECK: [[OUTER_FOO_INNER]] = {{.*}} ; [ DW_TAG_structure_type ] [inner] +// CHECK: [[OUTER_FOO_INNER]] = {{.*}}, null, metadata !"[[OUTER_FOO_INNER_ID:.*]]"} ; [ DW_TAG_structure_type ] [inner] // CHECK: metadata [[VIRT_MEM:![0-9]*]], i32 0, metadata !"_ZTS4virtI4elemE", metadata [[VIRT_TEMP_PARAM:![0-9]*]], metadata !"_ZTS4virtI4elemE"} ; [ DW_TAG_structure_type ] [virt<elem>] {{.*}} [def] // CHECK: [[VIRT_TEMP_PARAM]] = metadata !{metadata [[VIRT_T:![0-9]*]]} @@ -59,7 +59,7 @@ inline void func() { outer<foo>::inner x; -// CHECK: metadata [[OUTER_FOO_INNER]], i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x] +// CHECK: metadata !"[[OUTER_FOO_INNER_ID]]", i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x] template <typename T> struct virt { diff --git a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp new file mode 100644 index 0000000000000..cce84af4023c7 --- /dev/null +++ b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fstandalone-debug | FileCheck %s +namespace __pointer_type_imp +{ + template <class _Tp, class _Dp, bool > struct __pointer_type1 {}; + + // CHECK: metadata ![[PARAMS:[0-9]+]], metadata !"_ZTSN18__pointer_type_imp15__pointer_type1I1C14default_deleteIS1_ELb0EEE"} ; [ DW_TAG_structure_type ] [__pointer_type1<C, default_delete<C>, false>] [line [[@LINE+1]], size 8, align 8, offset 0] [def] [from ] + template <class _Tp, class _Dp> struct __pointer_type1<_Tp, _Dp, false> + { + typedef _Tp* type; + }; +} +template <class _Tp, class _Dp> +struct __pointer_type2 +{ + // Test that the bool template type parameter is emitted. + // + // CHECK: ![[PARAMS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata ![[FALSE:[0-9]+]]} + // CHECK: ![[FALSE]] = {{.*}} i8 0, {{.*}}} ; [ DW_TAG_template_value_parameter ] + typedef typename __pointer_type_imp::__pointer_type1<_Tp, _Dp, false>::type type; +}; +template <class _Tp> struct default_delete {}; +template <class _Tp, class _Dp = default_delete<_Tp> > class unique_ptr +{ + typedef typename __pointer_type2<_Tp, _Dp>::type pointer; + unique_ptr(pointer __p, _Dp __d) {} +}; +class C { + unique_ptr<C> Ptr; +}; +void foo(C &c) { +} diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index f58973bcceaeb..d071830eaf672 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,7 +1,7 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s // CHECK: {{.*}}, i1 false, metadata !"", i32 0, metadata !{{[0-9]]*}}, metadata [[RETAIN:![0-9]*]], {{.*}} ; [ DW_TAG_compile_unit ] -// CHECK: [[EMPTY:![0-9]*]] = metadata !{i32 0} +// CHECK: [[EMPTY:![0-9]*]] = metadata !{} // CHECK: [[RETAIN]] = metadata !{metadata !{{[0-9]]*}}, metadata [[FOO:![0-9]*]], @@ -50,8 +50,8 @@ // -// CHECK: [[TCNESTED:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEE9tmpl_implJLi1ELi2ELi3EEE", {{.*}} ; [ DW_TAG_structure_type ] [nested] -// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl>] +// CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEE9tmpl_implJLi1ELi2ELi3EEE", {{.*}}, metadata !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested] +// CHECK: metadata [[TCNARGS:![0-9]*]], metadata !"[[TCNT:.*]]"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl>] // CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCNARG8:![0-9]*]]} // CHECK: [[TCNARG1]] = {{.*}}metadata !"T", metadata [[INT]], {{.*}} ; [ DW_TAG_template_type_parameter ] // CHECK: [[TCNARG2]] = {{.*}}metadata !"", metadata [[INT]], i32 -3, {{.*}} ; [ DW_TAG_template_value_parameter ] @@ -77,9 +77,9 @@ // CHECK: [[PTOARG1]] = {{.*}}metadata !"", metadata [[CONST_PADDINGATEND_PTR:![0-9]*]], { i32, i8, [3 x i8] }* @PaddedObj, {{.*}} ; [ DW_TAG_template_value_parameter ] // CHECK: [[CONST_PADDINGATEND_PTR]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from _ZTS12PaddingAtEnd] -// CHECK: metadata [[TCNESTED]], i32 0, i32 1, %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested"* @tci, null} ; [ DW_TAG_variable ] [tci] +// CHECK: metadata !"[[TCNESTED]]", i32 0, i32 1, %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested"* @tci, null} ; [ DW_TAG_variable ] [tci] -// CHECK: metadata [[TCNT:![0-9]*]], i32 0, i32 1, %struct.TC* @tcn, null} ; [ DW_TAG_variable ] [tcn] +// CHECK: metadata !"[[TCNT]]", i32 0, i32 1, %struct.TC* @tcn, null} ; [ DW_TAG_variable ] [tcn] struct foo { char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero) int e; diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index 2a50895725344..1d6f1a77b49af 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -g -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -g -S -emit-llvm -o - | FileCheck %s struct A { virtual void f(); diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp index 852e14895618b..0f28a9063fb8e 100644 --- a/test/CodeGenCXX/debug-info-use-after-free.cpp +++ b/test/CodeGenCXX/debug-info-use-after-free.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -emit-llvm-only %s +// RUN: %clang_cc1 -g -triple %itanium_abi_triple -emit-llvm-only %s // Check that we don't crash. // PR12305, PR12315 diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp index a57e2f0a84ae6..6137400de07cd 100644 --- a/test/CodeGenCXX/debug-info-uuid.cpp +++ b/test/CodeGenCXX/debug-info-uuid.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -cxx-abi microsoft -g %s -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -g %s -o - -std=c++11 | FileCheck %s // RUN: not %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -g %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM // CHECK: metadata [[TGIARGS:![0-9]*]], null} ; [ DW_TAG_structure_type ] [tmpl_guid<&__uuidof(uuid)>] diff --git a/test/CodeGenCXX/debug-info-varargs.cpp b/test/CodeGenCXX/debug-info-varargs.cpp new file mode 100644 index 0000000000000..cc92477dbb926 --- /dev/null +++ b/test/CodeGenCXX/debug-info-varargs.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s + +struct A +{ + // CHECK-DAG: ", i32 [[@LINE+1]], metadata ![[ATY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[a] + void a(int c, ...) {} + // CHECK: ![[ATY]] ={{.*}} metadata ![[AARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] + // CHECK: ![[AARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]} + // CHECK: ![[UNSPEC]] = {{.*}} [ DW_TAG_unspecified_parameters ] +}; + + // CHECK: ", i32 [[@LINE+1]], metadata ![[BTY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[b] +void b(int c, ...) { + // CHECK: ![[BTY]] ={{.*}} metadata ![[BARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] + // CHECK: ![[BARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]} + + A a; + + // CHECK: metadata ![[PST:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [fptr] [line [[@LINE+1]]] + void (*fptr)(int, ...) = b; + // CHECK: ![[PST]] ={{.*}} metadata ![[BTY]]} ; [ DW_TAG_pointer_type ] +} diff --git a/test/CodeGenCXX/debug-info-vtable-optzn.cpp b/test/CodeGenCXX/debug-info-vtable-optzn.cpp new file mode 100644 index 0000000000000..c693f794b26f1 --- /dev/null +++ b/test/CodeGenCXX/debug-info-vtable-optzn.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -g -triple amd64-unknown-freebsd %s -o - | FileCheck %s +// +// This tests that the "emit debug info for a C++ class only in the +// module that has its vtable" optimization is disabled by default on +// Darwin and FreeBSD. +// +// CHECK: [ DW_TAG_member ] [lost] +class A +{ + virtual bool f() = 0; + int lost; +}; + +class B : public A +{ + B *g(); +}; + +B *B::g() { + return this; +} diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 93a4fe3f466a6..7c89dfc04ce1b 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -51,11 +51,6 @@ namespace VirtualBase { } } -void foo() { - const wchar_t c = L'x'; - wchar_t d = c; -} - namespace b5249287 { template <typename T> class A { struct B; @@ -77,7 +72,7 @@ foo func(foo f) { return f; // reference 'f' for now because otherwise we hit another bug } -// CHECK: [[FOO:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763:![0-9]*]], {{.*}} ; [ DW_TAG_structure_type ] [foo] +// CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763:![0-9]*]], {{.*}}, metadata !"[[FOO:.*]]"} ; [ DW_TAG_structure_type ] [foo] // CHECK: [[PR14763]] = {{.*}} ; [ DW_TAG_namespace ] [pr14763] // CHECK: [[INCTYPE:![0-9]*]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [decl] // CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN7pr162141aE"} ; [ DW_TAG_structure_type ] [a] @@ -88,6 +83,13 @@ foo func(foo f) { // CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] } +void foo() { + const wchar_t c = L'x'; + wchar_t d = c; +} + +// CHECK-NOT: ; [ DW_TAG_variable ] [c] + namespace pr9608 { // also pr9600 struct incomplete; incomplete (*x)[3]; @@ -96,8 +98,10 @@ incomplete (*x)[3]; // CHECK: [[INCARRAY]] = {{.*}}metadata !"_ZTSN6pr960810incompleteE", metadata {{![0-9]*}}, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from _ZTSN6pr960810incompleteE] } -// For some reason the argument for PR14763 ended up all the way down here -// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata [[FOO]], i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f] +// For some reason function arguments ended up down here +// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata !"[[FOO]]", i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f] + +// CHECK: ; [ DW_TAG_auto_variable ] [c] namespace pr16214 { struct a { diff --git a/test/CodeGenCXX/decl-ref-init.cpp b/test/CodeGenCXX/decl-ref-init.cpp index 1a82ee2b485bc..117d277c95e64 100644 --- a/test/CodeGenCXX/decl-ref-init.cpp +++ b/test/CodeGenCXX/decl-ref-init.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -emit-llvm %s -o - | \ +// RUN: FileCheck %s struct A {}; @@ -24,8 +23,5 @@ int main() { const A& rca2 = d(); } -// CHECK-LP64: callq __ZN1BcvR1AEv -// CHECK-LP64: callq __ZN1BcvR1AEv - -// CHECK-LP32: calll L__ZN1BcvR1AEv -// CHECK-LP32: calll L__ZN1BcvR1AEv +// CHECK: call dereferenceable({{[0-9]+}}) %struct.A* @_ZN1BcvR1AEv +// CHECK: call dereferenceable({{[0-9]+}}) %struct.A* @_ZN1BcvR1AEv diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp index 43756006f2093..6a7f43a512871 100644 --- a/test/CodeGenCXX/default-arg-temps.cpp +++ b/test/CodeGenCXX/default-arg-temps.cpp @@ -16,12 +16,12 @@ public: // CHECK-LABEL: define void @_Z1gv() void g() { // CHECK: call void @_ZN1TC1Ev([[T:%.*]]* [[AGG1:%.*]]) - // CHECK-NEXT: call void @_Z1fRK1T([[T]]* [[AGG1]]) + // CHECK-NEXT: call void @_Z1fRK1T([[T]]* dereferenceable({{[0-9]+}}) [[AGG1]]) // CHECK-NEXT: call void @_ZN1TD1Ev([[T]]* [[AGG1]]) f(); // CHECK-NEXT: call void @_ZN1TC1Ev([[T:%.*]]* [[AGG2:%.*]]) - // CHECK-NEXT: call void @_Z1fRK1T([[T]]* [[AGG2]]) + // CHECK-NEXT: call void @_Z1fRK1T([[T]]* dereferenceable({{[0-9]+}}) [[AGG2]]) // CHECK-NEXT: call void @_ZN1TD1Ev([[T]]* [[AGG2]]) f(); diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp index 83cae3afd5615..d364835850c3c 100644 --- a/test/CodeGenCXX/default-arguments.cpp +++ b/test/CodeGenCXX/default-arguments.cpp @@ -42,15 +42,15 @@ struct C { C(); }; -// CHECK-LABEL: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr -// CHECK: call void @_ZN1CC2Ev( - // CHECK-LABEL: define void @_ZN1CC2Ev(%struct.C* %this) unnamed_addr // CHECK: call void @_ZN2A1C1Ev( // CHECK: call void @_ZN2A2C1Ev( // CHECK: call void @_ZN1BC1ERK2A1RK2A2( // CHECK: call void @_ZN2A2D1Ev // CHECK: call void @_ZN2A1D1Ev + +// CHECK-LABEL: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr +// CHECK: call void @_ZN1CC2Ev( C::C() { } // CHECK-LABEL: define void @_Z2f3v() diff --git a/test/CodeGenCXX/default-constructor-default-argument.cpp b/test/CodeGenCXX/default-constructor-default-argument.cpp index 374a967e3e2a3..17ecc35645e9b 100644 --- a/test/CodeGenCXX/default-constructor-default-argument.cpp +++ b/test/CodeGenCXX/default-constructor-default-argument.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s // Check that call to constructor for struct A is generated correctly. struct A { A(int x = 2); }; diff --git a/test/CodeGenCXX/default-constructor-for-members.cpp b/test/CodeGenCXX/default-constructor-for-members.cpp index 6065b49ac1584..5eb8cd1767bb3 100644 --- a/test/CodeGenCXX/default-constructor-for-members.cpp +++ b/test/CodeGenCXX/default-constructor-for-members.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin -emit-llvm %s -o - | \ +// RUN: FileCheck %s extern "C" int printf(...); @@ -19,6 +18,4 @@ int main() { M m1; } -// CHECK-LP64: callq __ZN1SC1Ev - -// CHECK-LP32: calll L__ZN1SC1Ev +// CHECK: call void @_ZN1SC1Ev diff --git a/test/CodeGenCXX/default-constructor-template-member.cpp b/test/CodeGenCXX/default-constructor-template-member.cpp index 215696405a4fa..93df818460374 100644 --- a/test/CodeGenCXX/default-constructor-template-member.cpp +++ b/test/CodeGenCXX/default-constructor-template-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s template <class T> struct A { A(); }; struct B { A<int> x; }; diff --git a/test/CodeGenCXX/default-destructor-nested.cpp b/test/CodeGenCXX/default-destructor-nested.cpp index 565a7279c56ee..77b06d639f4c8 100644 --- a/test/CodeGenCXX/default-destructor-nested.cpp +++ b/test/CodeGenCXX/default-destructor-nested.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm-only +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm-only // PR6294 class A { diff --git a/test/CodeGenCXX/deferred-global-init.cpp b/test/CodeGenCXX/deferred-global-init.cpp index deb458f55c7dc..f64f507ac9198 100644 --- a/test/CodeGenCXX/deferred-global-init.cpp +++ b/test/CodeGenCXX/deferred-global-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s // PR5967 extern void* foo; @@ -11,6 +11,6 @@ void* bar() { return a; } // CHECK: load i8** @foo // CHECK: ret void -// CHECK-LABEL: define internal void @_GLOBAL__I_a +// CHECK-LABEL: define internal void @_GLOBAL__sub_I_deferred_global_init.cpp // CHECK: call void @__cxx_global_var_init() // CHECK: ret void diff --git a/test/CodeGenCXX/delayed-template-parsing.cpp b/test/CodeGenCXX/delayed-template-parsing.cpp index fa177d4562559..c5f4486415440 100644 --- a/test/CodeGenCXX/delayed-template-parsing.cpp +++ b/test/CodeGenCXX/delayed-template-parsing.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s namespace ClassScopeSpecialization { struct Type { diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp index f8e6bff295804..be3cf1a900e6b 100644 --- a/test/CodeGenCXX/delete-two-arg.cpp +++ b/test/CodeGenCXX/delete-two-arg.cpp @@ -1,4 +1,5 @@ -// RUN: not %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s +// expected-no-diagnostics typedef __typeof(sizeof(int)) size_t; diff --git a/test/CodeGenCXX/dependent-type-member-pointer.cpp b/test/CodeGenCXX/dependent-type-member-pointer.cpp index 99b8ecd555c79..595eca5aab2de 100644 --- a/test/CodeGenCXX/dependent-type-member-pointer.cpp +++ b/test/CodeGenCXX/dependent-type-member-pointer.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm-only -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm-only -verify %s // expected-no-diagnostics // PR7736 diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp index 675c50c423281..f4ef0e52772bf 100644 --- a/test/CodeGenCXX/derived-to-base-conv.cpp +++ b/test/CodeGenCXX/derived-to-base-conv.cpp @@ -33,9 +33,9 @@ void test0(X x) { test0_helper(x); // CHECK-LABEL: define void @_Z5test01X( // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align - // CHECK-NEXT: [[T0:%.*]] = call [[B:%.*]]* @_ZN1XcvR1BEv( + // CHECK-NEXT: [[T0:%.*]] = call dereferenceable({{[0-9]+}}) [[B:%.*]]* @_ZN1XcvR1BEv( // CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]* [[T0]] to [[A]]* - // CHECK-NEXT: call void @_ZN1AC1ERKS_([[A]]* [[TMP]], [[A]]* [[T1]]) + // CHECK-NEXT: call void @_ZN1AC1ERKS_([[A]]* [[TMP]], [[A]]* dereferenceable({{[0-9]+}}) [[T1]]) // CHECK-NEXT: call void @_Z12test0_helper1A([[A]]* [[TMP]]) // CHECK-NEXT: call void @_ZN1AD1Ev([[A]]* [[TMP]]) // CHECK-NEXT: ret void diff --git a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp index f2ecfc1d38cc1..d85928370319d 100644 --- a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp +++ b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s struct A { int i; }; struct B { char j; }; @@ -9,7 +9,7 @@ struct D final : virtual C { virtual void f(); }; -// CHECK-LABEL: define %struct.B* @_Z1fR1D +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.B* @_Z1fR1D B &f(D &d) { // CHECK-NOT: load i8** return d; diff --git a/test/CodeGenCXX/destructor-exception-spec.cpp b/test/CodeGenCXX/destructor-exception-spec.cpp index e111ba0ba8e52..50c17ef4aa10c 100644 --- a/test/CodeGenCXX/destructor-exception-spec.cpp +++ b/test/CodeGenCXX/destructor-exception-spec.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm-only %s -std=c++11 -// RUN: %clang_cc1 -emit-llvm-only -fno-use-cxa-atexit %s -std=c++11 -// RUN: %clang_cc1 -cxx-abi microsoft -fno-rtti -emit-llvm-only %s -std=c++11 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -std=c++11 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -fno-use-cxa-atexit %s -std=c++11 +// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm-only %s -std=c++11 // PR13479: don't crash with -fno-exceptions. namespace { diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 799cca28b4a4e..5c430480bc281 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -6,6 +6,13 @@ // CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev // CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev +// WIN32-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// WIN32-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev +// WIN32-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev +// WIN32-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev +// WIN32-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev + + struct A { int a; @@ -102,19 +109,19 @@ namespace test0 { B::~B() try { } catch (int i) {} // It will suppress the delegation optimization here, though. -// CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr +// CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr // CHECK: invoke void @_ZN5test06MemberD1Ev // CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] // CHECK: invoke void @_ZN5test04BaseD2Ev // CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: invoke void @_ZN5test05VBaseD2Ev -// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr +// CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr // CHECK: invoke void @_ZN5test06MemberD1Ev // CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] // CHECK: invoke void @_ZN5test04BaseD2Ev // CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK: invoke void @_ZN5test05VBaseD2Ev +// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] } // Test base-class aliasing. @@ -272,14 +279,6 @@ namespace test6 { // FIXME: way too much EH cleanup code follows C::~C() { opaque(); } - // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr - // CHECK: invoke void @_ZN5test61CD2Ev - // CHECK: invoke void @_ZN5test61BILj3EED2Ev - // CHECK: call void @_ZN5test61BILj2EED2Ev - // CHECK: ret void - // CHECK: invoke void @_ZN5test61BILj3EED2Ev - // CHECK: invoke void @_ZN5test61BILj2EED2Ev - // CHECK-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr // CHECK: invoke void @_ZN5test66opaqueEv // CHECK: invoke void @_ZN5test61AD1Ev @@ -293,6 +292,14 @@ namespace test6 { // CHECK: invoke void @_ZN5test61AD1Ev // CHECK: invoke void @_ZN5test61BILj1EED2Ev // CHECK: invoke void @_ZN5test61BILj0EED2Ev + + // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr + // CHECK: invoke void @_ZN5test61CD2Ev + // CHECK: invoke void @_ZN5test61BILj3EED2Ev + // CHECK: call void @_ZN5test61BILj2EED2Ev + // CHECK: ret void + // CHECK: invoke void @_ZN5test61BILj3EED2Ev + // CHECK: invoke void @_ZN5test61BILj2EED2Ev } // PR 9197 @@ -374,7 +381,7 @@ namespace test10 { // Checks from test3: - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr + // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr // CHECK: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev // CHECK: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]] // CHECK: ret void @@ -398,7 +405,7 @@ namespace test10 { // CHECK: call void @_ZN5test312_GLOBAL__N_11CD2Ev( // CHECK: ret void - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr + // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr // CHECK: invoke void @_ZN5test31BD2Ev( // CHECK: call void @_ZN5test31AD2Ev( // CHECK: ret void @@ -406,7 +413,7 @@ namespace test10 { // CHECK: declare void @_ZN5test31BD2Ev( // CHECK: declare void @_ZN5test31AD2Ev( - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr + // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( // CHECK: call void @_ZdlPv({{.*}}) [[NUW]] // CHECK: ret void diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp new file mode 100644 index 0000000000000..d913c09ec7be3 --- /dev/null +++ b/test/CodeGenCXX/dllexport-members.cpp @@ -0,0 +1,647 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Exported {}; +struct ExplicitDecl_Exported {}; +struct ExplicitInst_Exported {}; +struct ExplicitSpec_Exported {}; +struct ExplicitSpec_Def_Exported {}; +struct ExplicitSpec_InlineDef_Exported {}; +struct ExplicitSpec_NotExported {}; + +extern "C" void* malloc(__SIZE_TYPE__ size); +extern "C" void free(void* p); + + +//===----------------------------------------------------------------------===// +// Class members +//===----------------------------------------------------------------------===// + +// Export individual members of a class. +struct ExportMembers { + struct Nested; + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define dllexport void @"\01?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this) + // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?referencedNonExportedInClass@ExportMembers@@QAEXXZ" + __declspec(dllexport) void normalDef(); + __declspec(dllexport) void normalInclass() { referencedNonExportedInClass(); } + __declspec(dllexport) void normalInlineDef(); + __declspec(dllexport) inline void normalInlineDecl(); + void referencedNonExportedInClass() {} + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define dllexport void @"\01?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this) + __declspec(dllexport) virtual void virtualDef(); + __declspec(dllexport) virtual void virtualInclass() {} + __declspec(dllexport) virtual void virtualInlineDef(); + __declspec(dllexport) virtual inline void virtualInlineDecl(); + + // MSC-DAG: define dllexport void @"\01?staticDef@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@ExportMembers@@SAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers9staticDefEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers13staticInclassEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers15staticInlineDefEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers16staticInlineDeclEv() + __declspec(dllexport) static void staticDef(); + __declspec(dllexport) static void staticInclass() {} + __declspec(dllexport) static void staticInlineDef(); + __declspec(dllexport) static inline void staticInlineDecl(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define dllexport void @"\01?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this) + // MSC-DAG: define dllexport void @"\01?protectedStaticDef@ExportMembers@@KAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers18protectedStaticDefEv() +protected: + __declspec(dllexport) void protectedDef(); + __declspec(dllexport) static void protectedStaticDef(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define dllexport void @"\01?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this) + // MSC-DAG: define dllexport void @"\01?privateStaticDef@ExportMembers@@CAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers16privateStaticDefEv() +private: + __declspec(dllexport) void privateDef(); + __declspec(dllexport) static void privateStaticDef(); + + // M32-DAG: define x86_thiscallcc void @"\01?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this) + // M64-DAG: define void @"\01?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this) + // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this) + // G64-DAG: define void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this) +public: + void ignored(); + + // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4 + // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers14ConstexprFieldE = dllexport constant i32 1, align 4 + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; +}; + + void ExportMembers::normalDef() {} +inline void ExportMembers::normalInlineDef() {} + void ExportMembers::normalInlineDecl() {} + void ExportMembers::virtualDef() {} +inline void ExportMembers::virtualInlineDef() {} + void ExportMembers::virtualInlineDecl() {} + void ExportMembers::staticDef() {} +inline void ExportMembers::staticInlineDef() {} + void ExportMembers::staticInlineDecl() {} + void ExportMembers::ignored() {} + void ExportMembers::protectedDef() {} + void ExportMembers::protectedStaticDef() {} + void ExportMembers::privateDef() {} + void ExportMembers::privateStaticDef() {} + + int ExportMembers::StaticField = 1; +const int ExportMembers::StaticConstField = 1; +const int ExportMembers::StaticConstFieldEqualInit; +const int ExportMembers::StaticConstFieldBraceInit; +constexpr int ExportMembers::ConstexprField; + + +// Export individual members of a nested class. +struct ExportMembers::Nested { + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this) + __declspec(dllexport) void normalDef(); + __declspec(dllexport) void normalInclass() {} + __declspec(dllexport) void normalInlineDef(); + __declspec(dllexport) inline void normalInlineDecl(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this) + __declspec(dllexport) virtual void virtualDef(); + __declspec(dllexport) virtual void virtualInclass() {} + __declspec(dllexport) virtual void virtualInlineDef(); + __declspec(dllexport) virtual inline void virtualInlineDecl(); + + // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@Nested@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@Nested@ExportMembers@@SAXXZ"() + // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@Nested@ExportMembers@@SAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested9staticDefEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13staticInclassEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15staticInlineDefEv() + // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16staticInlineDeclEv() + __declspec(dllexport) static void staticDef(); + __declspec(dllexport) static void staticInclass() {} + __declspec(dllexport) static void staticInlineDef(); + __declspec(dllexport) static inline void staticInlineDecl(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this) + // MSC-DAG: define dllexport void @"\01?protectedStaticDef@Nested@ExportMembers@@KAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested18protectedStaticDefEv() +protected: + __declspec(dllexport) void protectedDef(); + __declspec(dllexport) static void protectedStaticDef(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this) + // MSC-DAG: define dllexport void @"\01?privateStaticDef@Nested@ExportMembers@@CAXXZ"() + // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested16privateStaticDefEv() +private: + __declspec(dllexport) void privateDef(); + __declspec(dllexport) static void privateStaticDef(); + + // M32-DAG: define x86_thiscallcc void @"\01?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this) + // M64-DAG: define void @"\01?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this) + // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this) + // G64-DAG: define void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this) +public: + void ignored(); + + // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4 + // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4 + // GNU-DAG: @_ZN13ExportMembers6Nested14ConstexprFieldE = dllexport constant i32 1, align 4 + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; +}; + + void ExportMembers::Nested::normalDef() {} +inline void ExportMembers::Nested::normalInlineDef() {} + void ExportMembers::Nested::normalInlineDecl() {} + void ExportMembers::Nested::virtualDef() {} +inline void ExportMembers::Nested::virtualInlineDef() {} + void ExportMembers::Nested::virtualInlineDecl() {} + void ExportMembers::Nested::staticDef() {} +inline void ExportMembers::Nested::staticInlineDef() {} + void ExportMembers::Nested::staticInlineDecl() {} + void ExportMembers::Nested::ignored() {} + void ExportMembers::Nested::protectedDef() {} + void ExportMembers::Nested::protectedStaticDef() {} + void ExportMembers::Nested::privateDef() {} + void ExportMembers::Nested::privateStaticDef() {} + + int ExportMembers::Nested::StaticField = 1; +const int ExportMembers::Nested::StaticConstField = 1; +const int ExportMembers::Nested::StaticConstFieldEqualInit; +const int ExportMembers::Nested::StaticConstFieldBraceInit; +constexpr int ExportMembers::Nested::ConstexprField; + + +// Export special member functions. +struct ExportSpecials { + // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this) + // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this) + __declspec(dllexport) ExportSpecials(); + + // M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this) + // M64-DAG: define dllexport void @"\01??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this) + __declspec(dllexport) ~ExportSpecials(); + + // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllexport) ExportSpecials(const ExportSpecials&); + + // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&); + + // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllexport) ExportSpecials(ExportSpecials&&); + + // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&); +}; +ExportSpecials::ExportSpecials() {} +ExportSpecials::~ExportSpecials() {} +ExportSpecials::ExportSpecials(const ExportSpecials&) {} +ExportSpecials& ExportSpecials::operator=(const ExportSpecials&) { return *this; } +ExportSpecials::ExportSpecials(ExportSpecials&&) {} +ExportSpecials& ExportSpecials::operator=(ExportSpecials&&) { return *this; } + + +// Export class with inline special member functions. +struct ExportInlineSpecials { + // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this) + // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@XZ"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1Ev( + // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1Ev( + __declspec(dllexport) ExportInlineSpecials() {} + + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportInlineSpecials@@QAE@XZ"( + // M64-DAG: define weak_odr dllexport void @"\01??1ExportInlineSpecials@@QEAA@XZ"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsD1Ev( + // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsD1Ev( + __declspec(dllexport) ~ExportInlineSpecials() {} + + // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@ABU0@@Z"( + // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@AEBU0@@Z"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1ERKS_( + // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1ERKS_( + __declspec(dllexport) inline ExportInlineSpecials(const ExportInlineSpecials&); + + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"( + // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_( + // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_( + __declspec(dllexport) ExportInlineSpecials& operator=(const ExportInlineSpecials&); + + // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@$$QAU0@@Z"( + // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1EOS_( + // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1EOS_( + __declspec(dllexport) ExportInlineSpecials(ExportInlineSpecials&&) {} + + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"( + // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"( + // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_( + // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_( + __declspec(dllexport) ExportInlineSpecials& operator=(ExportInlineSpecials&&) { return *this; } +}; +ExportInlineSpecials::ExportInlineSpecials(const ExportInlineSpecials&) {} +inline ExportInlineSpecials& ExportInlineSpecials::operator=(const ExportInlineSpecials&) { return *this; } + + +// Export defaulted member function definitions. +struct ExportDefaultedDefs { + __declspec(dllexport) ExportDefaultedDefs(); + __declspec(dllexport) ~ExportDefaultedDefs(); + __declspec(dllexport) inline ExportDefaultedDefs(const ExportDefaultedDefs&); + __declspec(dllexport) ExportDefaultedDefs& operator=(const ExportDefaultedDefs&); + __declspec(dllexport) ExportDefaultedDefs(ExportDefaultedDefs&&); + __declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&); +}; + +// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this) +// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this) +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default; + +// M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this) +// M64-DAG: define dllexport void @"\01??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this) +ExportDefaultedDefs::~ExportDefaultedDefs() = default; + +// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define weak_odr dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default; + +// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default; + +// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default; + +// M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}})) +ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default; + + +// Export allocation functions. +struct ExportAlloc { + __declspec(dllexport) void* operator new(__SIZE_TYPE__); + __declspec(dllexport) void* operator new[](__SIZE_TYPE__); + __declspec(dllexport) void operator delete(void*); + __declspec(dllexport) void operator delete[](void*); +}; + +// M32-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPAXI@Z"(i32 %n) +// M64-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPEAX_K@Z"(i64 %n) +// G32-DAG: define dllexport i8* @_ZN11ExportAllocnwEj(i32 %n) +// G64-DAG: define dllexport i8* @_ZN11ExportAllocnwEy(i64 %n) +void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); } + +// M32-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPAXI@Z"(i32 %n) +// M64-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPEAX_K@Z"(i64 %n) +// G32-DAG: define dllexport i8* @_ZN11ExportAllocnaEj(i32 %n) +// G64-DAG: define dllexport i8* @_ZN11ExportAllocnaEy(i64 %n) +void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); } + +// M32-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPAX@Z"(i8* %p) +// M64-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPEAX@Z"(i8* %p) +// G32-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p) +// G64-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p) +void ExportAlloc::operator delete(void* p) { free(p); } + +// M32-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPAX@Z"(i8* %p) +// M64-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPEAX@Z"(i8* %p) +// G32-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p) +// G64-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p) +void ExportAlloc::operator delete[](void* p) { free(p); } + + +//===----------------------------------------------------------------------===// +// Class member templates +//===----------------------------------------------------------------------===// + +struct MemFunTmpl { + template<typename T> void normalDef() {} + template<typename T> __declspec(dllexport) void exportedNormal() {} + template<typename T> static void staticDef() {} + template<typename T> __declspec(dllexport) static void exportedStatic() {} +}; + +// Export implicit instantiation of an exported member function template. +void useMemFunTmpl() { + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) + // M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) + // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) + // G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) + MemFunTmpl().exportedNormal<ImplicitInst_Exported>(); + + // MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"() + // GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ImplicitInst_ExportedEEvv() + MemFunTmpl().exportedStatic<ImplicitInst_Exported>(); +} + + +// Export explicit instantiation declaration of an exported member function +// template. +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this) +extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); + template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); + +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitDecl_ExportedEEvv() +extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); + template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); + + +// Export explicit instantiation definition of an exported member function +// template. +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) +template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>(); + +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitInst_ExportedEEvv() +template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>(); + + +// Export specialization of an exported member function template. +// M32-DAG: define dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define dllexport void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define dllexport void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this) +template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {} + +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this) +template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {} + +// MSC-DAG: define dllexport void @"\01??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define dllexport void @_ZN10MemFunTmpl14exportedStaticI25ExplicitSpec_Def_ExportedEEvv() +template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {} + +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI31ExplicitSpec_InlineDef_ExportedEEvv() +template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {} + + +// Not exporting specialization of an exported member function template without +// explicit dllexport. +// M32-DAG: define x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this) +template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {} + +// M32-DAG: define void @"\01??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define void @_ZN10MemFunTmpl14exportedStaticI24ExplicitSpec_NotExportedEEvv() +template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {} + + +// Export explicit instantiation declaration of a non-exported member function +// template. +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this) +extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); + template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); + +// M32-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ExportedEEvv() +extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); + template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); + + +// Export explicit instantiation definition of a non-exported member function +// template. +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this) +template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>(); + +// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ExportedEEvv() +template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>(); + + +// Export specialization of a non-exported member function template. +// M32-DAG: define dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define dllexport void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define dllexport void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this) +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this) +template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {} + +// MSC-DAG: define dllexport void @"\01??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"() +// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define dllexport void @_ZN10MemFunTmpl9staticDefI25ExplicitSpec_Def_ExportedEEvv() +// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ExportedEEvv() +template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Exported>() {} + + + +struct MemVarTmpl { + template<typename T> static const int StaticVar = 1; + template<typename T> __declspec(dllexport) static const int ExportedStaticVar = 1; +}; +template<typename T> const int MemVarTmpl::StaticVar; +template<typename T> const int MemVarTmpl::ExportedStaticVar; + +// Export implicit instantiation of an exported member variable template. +// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; } + +// Export explicit instantiation declaration of an exported member variable +// template. +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; + template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of an exported member variable +// template. +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>; + +// Export specialization of an exported member variable template. +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 +template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1; + +// Not exporting specialization of an exported member variable template without +// explicit dllexport. +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = constant i32 1, align 4 +template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported> = 1; + + +// Export explicit instantiation declaration of a non-exported member variable +// template. +// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; + template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of a non-exported member variable +// template. +// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>; + +// Export specialization of a non-exported member variable template. +// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 +template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1; diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp new file mode 100644 index 0000000000000..5097abf0c0942 --- /dev/null +++ b/test/CodeGenCXX/dllexport.cpp @@ -0,0 +1,686 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s + +// RUN: %clang_cc1 -triple i686-pc-win32 -O1 -mconstructor-aliases -std=c++1y -emit-llvm -o - %s | FileCheck %s --check-prefix=MSC --check-prefix=M32 + +// Helper structs to make templates more expressive. +struct ImplicitInst_Exported {}; +struct ExplicitDecl_Exported {}; +struct ExplicitInst_Exported {}; +struct ExplicitSpec_Exported {}; +struct ExplicitSpec_Def_Exported {}; +struct ExplicitSpec_InlineDef_Exported {}; +struct ExplicitSpec_NotExported {}; +struct External { int v; }; + +#define JOIN2(x, y) x##y +#define JOIN(x, y) JOIN2(x, y) +#define UNIQ(name) JOIN(name, __LINE__) +#define USEVAR(var) int UNIQ(use)() { return var; } +#define USE(func) void UNIQ(use)() { func(); } +#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; } +#define INSTVAR(var) template int var; +#define INST(func) template void func(); + +// The vftable for struct W is comdat largest because we have RTTI. +// M32-DAG: $"\01??_7W@@6B@" = comdat largest + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Declarations are not exported. +// MSC-NOT: @"\01?ExternGlobalDecl@@3HA" +// GNU-NOT: @ExternGlobalDecl +__declspec(dllexport) extern int ExternGlobalDecl; + +// dllexport implies a definition. +// MSC-DAG: @"\01?GlobalDef@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @GlobalDef = dllexport global i32 0, align 4 +__declspec(dllexport) int GlobalDef; + +// Export definition. +// MSC-DAG: @"\01?GlobalInit1@@3HA" = dllexport global i32 1, align 4 +// GNU-DAG: @GlobalInit1 = dllexport global i32 1, align 4 +__declspec(dllexport) int GlobalInit1 = 1; + +// MSC-DAG: @"\01?GlobalInit2@@3HA" = dllexport global i32 1, align 4 +// GNU-DAG: @GlobalInit2 = dllexport global i32 1, align 4 +int __declspec(dllexport) GlobalInit2 = 1; + +// Declare, then export definition. +// MSC-DAG: @"\01?GlobalDeclInit@@3HA" = dllexport global i32 1, align 4 +// GNU-DAG: @GlobalDeclInit = dllexport global i32 1, align 4 +__declspec(dllexport) extern int GlobalDeclInit; +int GlobalDeclInit = 1; + +// Redeclarations +// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @GlobalRedecl1 = dllexport global i32 0, align 4 +__declspec(dllexport) extern int GlobalRedecl1; +__declspec(dllexport) int GlobalRedecl1; + +// MSC-DAG: @"\01?GlobalRedecl2@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @GlobalRedecl2 = dllexport global i32 0, align 4 +__declspec(dllexport) extern int GlobalRedecl2; + int GlobalRedecl2; + +// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @_ZN2ns14ExternalGlobalE = dllexport global i32 0, align 4 +namespace ns { __declspec(dllexport) int ExternalGlobal; } + +// MSC-DAG: @"\01?ExternalAutoTypeGlobal@@3UExternal@@A" = dllexport global %struct.External zeroinitializer, align 4 +// GNU-DAG: @ExternalAutoTypeGlobal = dllexport global %struct.External zeroinitializer, align 4 +__declspec(dllexport) auto ExternalAutoTypeGlobal = External(); + +int f(); +// MSC-DAG: @"\01?x@?0??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0 +// MSC-DAG: @"\01?$S1@?0??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0 +int __declspec(dllexport) nonInlineStaticLocalsFunc() { + static int x = f(); + return x++; +}; + +// MSC-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dllexport global i32 0 +// MSC-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0 +// Note: MinGW doesn't seem to export the static local here. +inline int __declspec(dllexport) inlineStaticLocalsFunc() { + static int x = f(); + return x++; +} + + + +//===----------------------------------------------------------------------===// +// Variable templates +//===----------------------------------------------------------------------===// + +// 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 dllexport global +// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dllexport global +template<typename T> __declspec(dllexport) int VarTmplImplicitDef; +USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>) + +// Export definition. +// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template<typename T> __declspec(dllexport) int VarTmplInit1 = 1; +INSTVAR(VarTmplInit1<ExplicitInst_Exported>) + +// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template<typename T> int __declspec(dllexport) VarTmplInit2 = 1; +INSTVAR(VarTmplInit2<ExplicitInst_Exported>) + +// Declare, then export definition. +// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template<typename T> __declspec(dllexport) extern int VarTmplDeclInit; +template<typename T> int VarTmplDeclInit = 1; +INSTVAR(VarTmplDeclInit<ExplicitInst_Exported>) + +// Redeclarations +// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template<typename T> __declspec(dllexport) extern int VarTmplRedecl1; +template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1; +INSTVAR(VarTmplRedecl1<ExplicitInst_Exported>) + +// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template<typename T> __declspec(dllexport) extern int VarTmplRedecl2; +template<typename T> int VarTmplRedecl2 = 1; +INSTVAR(VarTmplRedecl2<ExplicitInst_Exported>) + +// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, align 4 +namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; } +INSTVAR(ns::ExternalVarTmpl<ExplicitInst_Exported>) + +// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, align 4 +// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, align 4 +template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); +template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>; + + +template<typename T> int VarTmpl = 1; +template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1; + +// Export implicit instantiation of an exported variable template. +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +USEVAR(ExportedVarTmpl<ImplicitInst_Exported>) + +// Export explicit instantiation declaration of an exported variable template. +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +extern template int ExportedVarTmpl<ExplicitDecl_Exported>; + template int ExportedVarTmpl<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of an exported variable template. +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>; + +// Export specialization of an exported variable template. +// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4 +template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>; + +// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4 +template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1; + +// Not exporting specialization of an exported variable template without +// explicit dllexport. +// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = global i32 0, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI24ExplicitSpec_NotExportedE = global i32 0, align 4 +template<> int ExportedVarTmpl<ExplicitSpec_NotExported>; + + +// Export explicit instantiation declaration of a non-exported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; + template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of a non-exported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>; + +// Export specialization of a non-exported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4 +template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>; + +// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4 +// GNU-DAG: @_Z7VarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4 +template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1; + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Declarations are not exported. + +// Export function definition. +// MSC-DAG: define dllexport void @"\01?def@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z3defv() +__declspec(dllexport) void def() {} + +// extern "C" +// MSC-DAG: define dllexport void @externC() +// GNU-DAG: define dllexport void @externC() +extern "C" __declspec(dllexport) void externC() {} + +// Export inline function. +// MSC-DAG: define weak_odr dllexport void @"\01?inlineFunc@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z10inlineFuncv() +__declspec(dllexport) inline void inlineFunc() {} + +// MSC-DAG: define weak_odr dllexport void @"\01?inlineDecl@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z10inlineDeclv() +__declspec(dllexport) inline void inlineDecl(); + void inlineDecl() {} + +// MSC-DAG: define weak_odr dllexport void @"\01?inlineDef@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z9inlineDefv() +__declspec(dllexport) void inlineDef(); + inline void inlineDef() {} + +// Redeclarations +// MSC-DAG: define dllexport void @"\01?redecl1@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z7redecl1v() +__declspec(dllexport) void redecl1(); +__declspec(dllexport) void redecl1() {} + +// MSC-DAG: define dllexport void @"\01?redecl2@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z7redecl2v() +__declspec(dllexport) void redecl2(); + void redecl2() {} + +// Friend functions +// MSC-DAG: define dllexport void @"\01?friend1@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z7friend1v() +// MSC-DAG: define dllexport void @"\01?friend2@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z7friend2v() +struct FuncFriend { + friend __declspec(dllexport) void friend1(); + friend __declspec(dllexport) void friend2(); +}; +__declspec(dllexport) void friend1() {} + void friend2() {} + +// Implicit declarations can be redeclared with dllexport. +// MSC-DAG: define dllexport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"( +// GNU-DAG: define dllexport noalias i8* @_Znw{{[yj]}}( +void* alloc(__SIZE_TYPE__ n); +__declspec(dllexport) void* operator new(__SIZE_TYPE__ n) { return alloc(n); } + +// MSC-DAG: define dllexport void @"\01?externalFunc@ns@@YAXXZ"() +// GNU-DAG: define dllexport void @_ZN2ns12externalFuncEv() +namespace ns { __declspec(dllexport) void externalFunc() {} } + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Export function template definition. +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z11funcTmplDefI21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) void funcTmplDef() {} +INST(funcTmplDef<ExplicitInst_Exported>) + +// Export inline function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl1I21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {} +INST(inlineFuncTmpl1<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl2I21ExplicitInst_ExportedEvv() +template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {} +INST(inlineFuncTmpl2<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z18inlineFuncTmplDeclI21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} +INST(inlineFuncTmplDecl<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z17inlineFuncTmplDefI21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} +INST(inlineFuncTmplDef<ExplicitInst_Exported>) + + +// Redeclarations +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl1I21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) void funcTmplRedecl1(); +template<typename T> __declspec(dllexport) void funcTmplRedecl1() {} +INST(funcTmplRedecl1<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl2I21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) void funcTmplRedecl2(); +template<typename T> void funcTmplRedecl2() {} +INST(funcTmplRedecl2<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl3I21ExplicitInst_ExportedEvv() +template<typename T> __declspec(dllexport) void funcTmplRedecl3(); +template<typename T> void funcTmplRedecl3() {} +INST(funcTmplRedecl3<ExplicitInst_Exported>) + + +// Function template friends +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend1I21ExplicitInst_ExportedEvv() +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend2I21ExplicitInst_ExportedEvv() +struct FuncTmplFriend { + template<typename T> friend __declspec(dllexport) void funcTmplFriend1(); + template<typename T> friend __declspec(dllexport) void funcTmplFriend2(); +}; +template<typename T> __declspec(dllexport) void funcTmplFriend1() {} +template<typename T> void funcTmplFriend2() {} +INST(funcTmplFriend1<ExplicitInst_Exported>) +INST(funcTmplFriend2<ExplicitInst_Exported>) + +// MSC-DAG: define weak_odr dllexport void @"\01??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_ZN2ns16externalFuncTmplI21ExplicitInst_ExportedEEvv() +namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl() {} } +INST(ns::externalFuncTmpl<ExplicitInst_Exported>) + + +template<typename T> void funcTmpl() {} +template<typename T> __declspec(dllexport) void exportedFuncTmpl() {} + +// Export implicit instantiation of an exported function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ImplicitInst_ExportedEvv() +USE(exportedFuncTmpl<ImplicitInst_Exported>) + +// Export explicit instantiation declaration of an exported function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitDecl_ExportedEvv() +extern template void exportedFuncTmpl<ExplicitDecl_Exported>(); + template void exportedFuncTmpl<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of an exported function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitInst_ExportedEvv() +template void exportedFuncTmpl<ExplicitInst_Exported>(); + +// Export specialization of an exported function template. +// MSC-DAG: define dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z16exportedFuncTmplI25ExplicitSpec_Def_ExportedEvv() +template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {} + +// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI31ExplicitSpec_InlineDef_ExportedEvv() +template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {} + +// Not exporting specialization of an exported function template without +// explicit dllexport. +// MSC-DAG: define void @"\01??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"() +// GNU-DAG: define void @_Z16exportedFuncTmplI24ExplicitSpec_NotExportedEvv() +template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {} + + +// Export explicit instantiation declaration of a non-exported function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitDecl_ExportedEvv() +extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); + template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of a non-exported function template. +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitInst_ExportedEvv() +template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>(); + +// Export specialization of a non-exported function template. +// MSC-DAG: define dllexport void @"\01??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"() +// GNU-DAG: define dllexport void @_Z8funcTmplI25ExplicitSpec_Def_ExportedEvv() +template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {} + +// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"() +// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ExportedEvv() +template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {} + + + +//===----------------------------------------------------------------------===// +// Precedence +//===----------------------------------------------------------------------===// + +// dllexport takes precedence over the dllimport if both are specified. +// MSC-DAG: @"\01?PrecedenceGlobal1A@@3HA" = dllexport global i32 0, align 4 +// MSC-DAG: @"\01?PrecedenceGlobal1B@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobal1A = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobal1B = dllexport global i32 0, align 4 +__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // dllimport ignored +__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // dllimport ignored + +// MSC-DAG: @"\01?PrecedenceGlobal2A@@3HA" = dllexport global i32 0, align 4 +// MSC-DAG: @"\01?PrecedenceGlobal2B@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobal2A = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobal2B = dllexport global i32 0, align 4 +__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // dllimport ignored +__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // dllimport ignored + +// MSC-DAG: @"\01?PrecedenceGlobalRedecl1@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobalRedecl1 = dllexport global i32 0, align 4 +__declspec(dllexport) extern int PrecedenceGlobalRedecl1; +__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0; + +// MSC-DAG: @"\01?PrecedenceGlobalRedecl2@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobalRedecl2 = dllexport global i32 0, align 4 +__declspec(dllimport) extern int PrecedenceGlobalRedecl2; +__declspec(dllexport) int PrecedenceGlobalRedecl2; + +// MSC-DAG: @"\01?PrecedenceGlobalMixed1@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobalMixed1 = dllexport global i32 0, align 4 +__attribute__((dllexport)) extern int PrecedenceGlobalMixed1; +__declspec(dllimport) int PrecedenceGlobalMixed1 = 0; + +// MSC-DAG: @"\01?PrecedenceGlobalMixed2@@3HA" = dllexport global i32 0, align 4 +// GNU-DAG: @PrecedenceGlobalMixed2 = dllexport global i32 0, align 4 +__attribute__((dllimport)) extern int PrecedenceGlobalMixed2; +__declspec(dllexport) int PrecedenceGlobalMixed2; + +// MSC-DAG: define dllexport void @"\01?precedence1A@@YAXXZ" +// MSC-DAG: define dllexport void @"\01?precedence1B@@YAXXZ" +// GNU-DAG: define dllexport void @_Z12precedence1Av() +// GNU-DAG: define dllexport void @_Z12precedence1Bv() +void __attribute__((dllimport, dllexport)) precedence1A() {} +void __declspec(dllimport) __declspec(dllexport) precedence1B() {} + +// MSC-DAG: define dllexport void @"\01?precedence2A@@YAXXZ" +// MSC-DAG: define dllexport void @"\01?precedence2B@@YAXXZ" +// GNU-DAG: define dllexport void @_Z12precedence2Av() +// GNU-DAG: define dllexport void @_Z12precedence2Bv() +void __attribute__((dllexport, dllimport)) precedence2A() {} +void __declspec(dllexport) __declspec(dllimport) precedence2B() {} + +// MSC-DAG: define dllexport void @"\01?precedenceRedecl1@@YAXXZ" +// GNU-DAG: define dllexport void @_Z17precedenceRedecl1v() +void __declspec(dllimport) precedenceRedecl1(); +void __declspec(dllexport) precedenceRedecl1() {} + +// MSC-DAG: define dllexport void @"\01?precedenceRedecl2@@YAXXZ" +// GNU-DAG: define dllexport void @_Z17precedenceRedecl2v() +void __declspec(dllexport) precedenceRedecl2(); +void __declspec(dllimport) precedenceRedecl2() {} + + + +//===----------------------------------------------------------------------===// +// Classes +//===----------------------------------------------------------------------===// + +struct S { + void __declspec(dllexport) a() {} + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ" + + struct T { + void __declspec(dllexport) a() {} + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@S@@QAEXXZ" + }; +}; + + +struct __declspec(dllexport) T { + // Copy assignment operator: + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@ABU0@@Z" + + // Explicitly defaulted copy constructur: + T(const T&) = default; + // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z" + + void a() {} + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ" + + static int b; + // M32-DAG: @"\01?b@T@@2HA" = external dllexport global i32 + + static int c; + // M32-DAG: @"\01?c@T@@2HA" = dllexport global i32 0, align 4 +}; + +USEVAR(T::b) +int T::c; + +template <typename T> struct __declspec(dllexport) U { void foo() {} }; +// The U<int> specialization below must cause the following to be emitted: +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ" +// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z" +struct __declspec(dllexport) V : public U<int> { }; + + +struct __declspec(dllexport) W { virtual void foo() {} }; +// Default ctor: +// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@XZ" +// Copy ctor: +// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z" +// vftable: +// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat $"\01??_7W@@6B@" +// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[W_VTABLE]], i32 0, i32 1) +// G32-DAG: @_ZTV1W = weak_odr dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] + +struct __declspec(dllexport) X : public virtual W {}; +// vbtable: +// M32-DAG: @"\01??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4] + +struct __declspec(dllexport) Y { + // Move assignment operator: + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.Y* @"\01??4Y@@QAEAAU0@$$QAU0@@Z" + + int x; +}; + +struct __declspec(dllexport) Z { virtual ~Z() {} }; +// The scalar deleting dtor does not get exported: +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_GZ@@UAEPAXI@Z" + + +// The user-defined dtor does get exported: +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1Z@@UAE@XZ" + +namespace DontUseDtorAlias { + struct __declspec(dllexport) A { ~A(); }; + struct __declspec(dllexport) B : A { ~B(); }; + A::~A() { } + B::~B() { } + // Emit a real definition of B's constructor; don't alias it to A's. + // M32-DAG: define dllexport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ" +} + +struct __declspec(dllexport) DefaultedCtorsDtors { + DefaultedCtorsDtors() = default; + // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ" + ~DefaultedCtorsDtors() = default; + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ" +}; + +namespace ReferencedInlineMethodInNestedClass { + struct __declspec(dllexport) S { + void foo() { + t->bar(); + } + struct T { + void bar() {} + }; + T *t; + }; + // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ" + // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ" +} + +// MS ignores DLL attributes on partial specializations. +template <typename T> struct PartiallySpecializedClassTemplate {}; +template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f() {} }; +USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f); +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv + +template <typename T> struct ExplicitlySpecializedClassTemplate {}; +template <> struct __declspec(dllexport) ExplicitlySpecializedClassTemplate<void*> { void f() {} }; +USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template <typename T> struct ClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; + +template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; +template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; + +template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; +template struct ExplicitlyInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; + + +// MS: ClassTemplate<int> gets exported. +struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {}; +USEMEMFUNC(ClassTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv + +// ExportedTemplate is explicitly exported. +struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv + +// ImportedClassTemplate is explicitly imported. +struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; +USEMEMFUNC(ImportedClassTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv + +// Base class already instantiated without dll attribute. +struct DerivedFromTemplateD : public ClassTemplate<double> {}; +struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; +USEMEMFUNC(ClassTemplate<double>, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv + +// MS: Base class already instantiated with different dll attribute. +struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {}; +struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; +USEMEMFUNC(ClassTemplate<bool>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv + +// Base class already specialized without dll attribute. +struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv + +// Base class alredy specialized with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv + +// Base class already specialized with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv + +// Base class already instantiated without dll attribute. +struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func) +// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv + +// MS: A dll attribute propagates through multiple levels of instantiation. +template <typename T> struct TopClass { void func() {} }; +template <typename T> struct MiddleClass : public TopClass<T> { }; +struct __declspec(dllexport) BottomClass : public MiddleClass<int> { }; +USEMEMFUNC(TopClass<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp new file mode 100644 index 0000000000000..6656b92b00225 --- /dev/null +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -0,0 +1,875 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O1 -o - %s -DMSABI | FileCheck --check-prefix=MO1 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O1 -o - %s | FileCheck --check-prefix=GO1 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Imported {}; +struct ExplicitDecl_Imported {}; +struct ExplicitInst_Imported {}; +struct ExplicitSpec_Imported {}; +struct ExplicitSpec_Def_Imported {}; +struct ExplicitSpec_InlineDef_Imported {}; +struct ExplicitSpec_NotImported {}; + +#define JOIN2(x, y) x##y +#define JOIN(x, y) JOIN2(x, y) +#define UNIQ(name) JOIN(name, __LINE__) +#define USE(func) void UNIQ(use)() { func(); } +#define USEMV(cls, var) int UNIQ(use)() { return ref(cls::var); } +#define USEMF(cls, fun) template<> void useMemFun<__LINE__, cls>() { cls().fun(); } +#define USESPECIALS(cls) void UNIQ(use)() { useSpecials<cls>(); } + +template<typename T> +T ref(T const& v) { return v; } + +template<int Line, typename T> +void useMemFun(); + +template<typename T> +void useSpecials() { + T v; // Default constructor + + T c1(static_cast<const T&>(v)); // Copy constructor + T c2 = static_cast<const T&>(v); // Copy constructor + T c3; + c3 = static_cast<const T&>(v); // Copy assignment + + T m1(static_cast<T&&>(v)); // Move constructor + T m2 = static_cast<T&&>(v); // Move constructor + T m3; + m3 = static_cast<T&&>(v); // Move assignment +} + +// Used to force non-trivial special members. +struct ForceNonTrivial { + ForceNonTrivial(); + ~ForceNonTrivial(); + ForceNonTrivial(const ForceNonTrivial&); + ForceNonTrivial& operator=(const ForceNonTrivial&); + ForceNonTrivial(ForceNonTrivial&&); + ForceNonTrivial& operator=(ForceNonTrivial&&); +}; + + + +//===----------------------------------------------------------------------===// +// Class members +//===----------------------------------------------------------------------===// + +// Import individual members of a class. +struct ImportMembers { + struct Nested; + + // M32-DAG: define x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this) + // M64-DAG: define void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) + // G64-DAG: define void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv( + __declspec(dllimport) void normalDef(); // dllimport ignored + __declspec(dllimport) void normalDecl(); + __declspec(dllimport) void normalInclass() {} + __declspec(dllimport) void normalInlineDef(); + __declspec(dllimport) inline void normalInlineDecl(); + + // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this) + // M64-DAG: define void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) + // G64-DAG: define void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv( + __declspec(dllimport) virtual void virtualDef(); // dllimport ignored + __declspec(dllimport) virtual void virtualDecl(); + __declspec(dllimport) virtual void virtualInclass() {} + __declspec(dllimport) virtual void virtualInlineDef(); + __declspec(dllimport) virtual inline void virtualInlineDecl(); + + // MSC-DAG: define void @"\01?staticDef@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"() + // GNU-DAG: define void @_ZN13ImportMembers9staticDefEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers13staticInclassEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers15staticInlineDefEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers16staticInlineDeclEv() + // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"() + // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() + // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers13staticInclassEv() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers15staticInlineDefEv() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers16staticInlineDeclEv() + __declspec(dllimport) static void staticDef(); // dllimport ignored + __declspec(dllimport) static void staticDecl(); + __declspec(dllimport) static void staticInclass() {} + __declspec(dllimport) static void staticInlineDef(); + __declspec(dllimport) static inline void staticInlineDecl(); + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*) + // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@ImportMembers@@KAXXZ"() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers19protectedStaticDeclEv() +protected: + __declspec(dllimport) void protectedNormalDecl(); + __declspec(dllimport) static void protectedStaticDecl(); + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*) + // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@ImportMembers@@CAXXZ"() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers17privateStaticDeclEv() +private: + __declspec(dllimport) void privateNormalDecl(); + __declspec(dllimport) static void privateStaticDecl(); + + // M32-DAG: declare x86_thiscallcc void @"\01?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare void @"\01?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*) + // G64-DAG: declare void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*) +public: + void ignored(); + + // MSC-DAG: @"\01?StaticField@ImportMembers@@2HA" = external dllimport global i32 + // MSC-DAG: @"\01?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // MSC-DAG: @"\01?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // GNU-DAG: @_ZN13ImportMembers11StaticFieldE = external dllimport global i32 + // GNU-DAG: @_ZN13ImportMembers16StaticConstFieldE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers25StaticConstFieldEqualInitE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers25StaticConstFieldBraceInitE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers14ConstexprFieldE = external dllimport constant i32 + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + + template<int Line, typename T> friend void useMemFun(); +}; + + void ImportMembers::normalDef() {} // dllimport ignored +inline void ImportMembers::normalInlineDef() {} + void ImportMembers::normalInlineDecl() {} + void ImportMembers::virtualDef() {} // dllimport ignored +inline void ImportMembers::virtualInlineDef() {} + void ImportMembers::virtualInlineDecl() {} + void ImportMembers::staticDef() {} // dllimport ignored +inline void ImportMembers::staticInlineDef() {} + void ImportMembers::staticInlineDecl() {} + +USEMF(ImportMembers, normalDef) +USEMF(ImportMembers, normalDecl) +USEMF(ImportMembers, normalInclass) +USEMF(ImportMembers, normalInlineDef) +USEMF(ImportMembers, normalInlineDecl) +USEMF(ImportMembers, virtualDef) +USEMF(ImportMembers, virtualDecl) +USEMF(ImportMembers, virtualInclass) +USEMF(ImportMembers, virtualInlineDef) +USEMF(ImportMembers, virtualInlineDecl) +USEMF(ImportMembers, staticDef) +USEMF(ImportMembers, staticDecl) +USEMF(ImportMembers, staticInclass) +USEMF(ImportMembers, staticInlineDef) +USEMF(ImportMembers, staticInlineDecl) +USEMF(ImportMembers, protectedNormalDecl) +USEMF(ImportMembers, protectedStaticDecl) +USEMF(ImportMembers, privateNormalDecl) +USEMF(ImportMembers, privateStaticDecl) +USEMF(ImportMembers, ignored) + +USEMV(ImportMembers, StaticField) +USEMV(ImportMembers, StaticConstField) +USEMV(ImportMembers, StaticConstFieldEqualInit) +USEMV(ImportMembers, StaticConstFieldBraceInit) +USEMV(ImportMembers, ConstexprField) + + +// Import individual members of a nested class. +struct ImportMembers::Nested { + // M32-DAG: define x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this) + // M64-DAG: define void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv( + __declspec(dllimport) void normalDef(); // dllimport ignored + __declspec(dllimport) void normalDecl(); + __declspec(dllimport) void normalInclass() {} + __declspec(dllimport) void normalInlineDef(); + __declspec(dllimport) inline void normalInlineDecl(); + + // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this) + // M64-DAG: define void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*) + + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"( + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv( + __declspec(dllimport) virtual void virtualDef(); // dllimport ignored + __declspec(dllimport) virtual void virtualDecl(); + __declspec(dllimport) virtual void virtualInclass() {} + __declspec(dllimport) virtual void virtualInlineDef(); + __declspec(dllimport) virtual inline void virtualInlineDecl(); + + // MSC-DAG: define void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() + // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"() + // GNU-DAG: define void @_ZN13ImportMembers6Nested9staticDefEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested13staticInclassEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv() + // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"() + // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() + // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested13staticInclassEv() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv() + // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv() + __declspec(dllimport) static void staticDef(); // dllimport ignored + __declspec(dllimport) static void staticDecl(); + __declspec(dllimport) static void staticInclass() {} + __declspec(dllimport) static void staticInlineDef(); + __declspec(dllimport) static inline void staticInlineDecl(); + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*) + // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedStaticDeclEv() +protected: + __declspec(dllimport) void protectedNormalDecl(); + __declspec(dllimport) static void protectedStaticDecl(); + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*) + // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@Nested@ImportMembers@@CAXXZ"() + // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateStaticDeclEv() +private: + __declspec(dllimport) void privateNormalDecl(); + __declspec(dllimport) static void privateStaticDecl(); + + // M32-DAG: declare x86_thiscallcc void @"\01?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare void @"\01?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*) +public: + void ignored(); + + // MSC-DAG: @"\01?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32 + // MSC-DAG: @"\01?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // MSC-DAG: @"\01?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4 + // GNU-DAG: @_ZN13ImportMembers6Nested11StaticFieldE = external dllimport global i32 + // GNU-DAG: @_ZN13ImportMembers6Nested16StaticConstFieldE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldEqualInitE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldBraceInitE = external dllimport constant i32 + // GNU-DAG: @_ZN13ImportMembers6Nested14ConstexprFieldE = external dllimport constant i32 + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + + template<int Line, typename T> friend void useMemFun(); +}; + + void ImportMembers::Nested::normalDef() {} // dllimport ignored +inline void ImportMembers::Nested::normalInlineDef() {} + void ImportMembers::Nested::normalInlineDecl() {} + void ImportMembers::Nested::virtualDef() {} // dllimport ignored +inline void ImportMembers::Nested::virtualInlineDef() {} + void ImportMembers::Nested::virtualInlineDecl() {} + void ImportMembers::Nested::staticDef() {} // dllimport ignored +inline void ImportMembers::Nested::staticInlineDef() {} + void ImportMembers::Nested::staticInlineDecl() {} + +USEMF(ImportMembers::Nested, normalDef) +USEMF(ImportMembers::Nested, normalDecl) +USEMF(ImportMembers::Nested, normalInclass) +USEMF(ImportMembers::Nested, normalInlineDef) +USEMF(ImportMembers::Nested, normalInlineDecl) +USEMF(ImportMembers::Nested, virtualDef) +USEMF(ImportMembers::Nested, virtualDecl) +USEMF(ImportMembers::Nested, virtualInclass) +USEMF(ImportMembers::Nested, virtualInlineDef) +USEMF(ImportMembers::Nested, virtualInlineDecl) +USEMF(ImportMembers::Nested, staticDef) +USEMF(ImportMembers::Nested, staticDecl) +USEMF(ImportMembers::Nested, staticInclass) +USEMF(ImportMembers::Nested, staticInlineDef) +USEMF(ImportMembers::Nested, staticInlineDecl) +USEMF(ImportMembers::Nested, protectedNormalDecl) +USEMF(ImportMembers::Nested, protectedStaticDecl) +USEMF(ImportMembers::Nested, privateNormalDecl) +USEMF(ImportMembers::Nested, privateStaticDecl) +USEMF(ImportMembers::Nested, ignored) + +USEMV(ImportMembers::Nested, StaticField) +USEMV(ImportMembers::Nested, StaticConstField) +USEMV(ImportMembers::Nested, StaticConstFieldEqualInit) +USEMV(ImportMembers::Nested, StaticConstFieldBraceInit) +USEMV(ImportMembers::Nested, ConstexprField) + + +// Import special member functions. +struct ImportSpecials { + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned) + // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*) + // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*) + __declspec(dllimport) ImportSpecials(); + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*) + // M64-DAG: declare dllimport void @"\01??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*) + // G64-DAG: declare dllimport void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*) + __declspec(dllimport) ~ImportSpecials(); + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportSpecials(const ImportSpecials&); + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportSpecials& operator=(const ImportSpecials&); + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportSpecials(ImportSpecials&&); + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportSpecials& operator=(ImportSpecials&&); +}; +USESPECIALS(ImportSpecials) + + +// Export inline special member functions. +struct ImportInlineSpecials { + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*) + // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev( + __declspec(dllimport) ImportInlineSpecials() {} + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*) + // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*) + // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev( + __declspec(dllimport) ~ImportInlineSpecials() {} + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_( + __declspec(dllimport) inline ImportInlineSpecials(const ImportInlineSpecials&); + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_( + __declspec(dllimport) ImportInlineSpecials& operator=(const ImportInlineSpecials&); + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_( + __declspec(dllimport) ImportInlineSpecials(ImportInlineSpecials&&) {} + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"( + // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_( + __declspec(dllimport) ImportInlineSpecials& operator=(ImportInlineSpecials&&) { return *this; } +}; +ImportInlineSpecials::ImportInlineSpecials(const ImportInlineSpecials&) {} +inline ImportInlineSpecials& ImportInlineSpecials::operator=(const ImportInlineSpecials&) { return *this; } +USESPECIALS(ImportInlineSpecials) + + +// Import defaulted member functions. +struct ImportDefaulted { + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*) + // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this) + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this) + __declspec(dllimport) ImportDefaulted() = default; + + // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*) + // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*) + // G64-DAG: declare dllimport void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*) + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this) + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this) + __declspec(dllimport) ~ImportDefaulted() = default; + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default; + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default; + + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default; + + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + __declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default; + + ForceNonTrivial v; // ensure special members are non-trivial +}; +USESPECIALS(ImportDefaulted) + + +// Import defaulted member function definitions. +struct ImportDefaultedDefs { + __declspec(dllimport) inline ImportDefaultedDefs(); + __declspec(dllimport) inline ~ImportDefaultedDefs(); + + __declspec(dllimport) ImportDefaultedDefs(const ImportDefaultedDefs&); + __declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&); + + __declspec(dllimport) ImportDefaultedDefs(ImportDefaultedDefs&&); + __declspec(dllimport) ImportDefaultedDefs& operator=(ImportDefaultedDefs&&); +}; + +// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned) +// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*) +// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*) +__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; + +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*) +// M64-DAG: declare dllimport void @"\01??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*) +// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*) +__declspec(dllimport) ImportDefaultedDefs::~ImportDefaultedDefs() = default; + +// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default; + +// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; + +// M32-DAG: define x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored + +// M32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored + +USESPECIALS(ImportDefaultedDefs) + + +// Import allocation functions. +struct ImportAlloc { + __declspec(dllimport) void* operator new(__SIZE_TYPE__); + __declspec(dllimport) void* operator new[](__SIZE_TYPE__); + __declspec(dllimport) void operator delete(void*); + __declspec(dllimport) void operator delete[](void*); +}; + +// M32-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPAXI@Z"(i32) +// M64-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPEAX_K@Z"(i64) +// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnwEj(i32) +// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnwEy(i64) +void UNIQ(use)() { new ImportAlloc(); } + +// M32-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPAXI@Z"(i32) +// M64-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPEAX_K@Z"(i64) +// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnaEj(i32) +// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnaEy(i64) +void UNIQ(use)() { new ImportAlloc[1]; } + +// M32-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPAX@Z"(i8*) +// M64-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPEAX@Z"(i8*) +// G32-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*) +// G64-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*) +void UNIQ(use)(ImportAlloc* ptr) { delete ptr; } + +// M32-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPAX@Z"(i8*) +// M64-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPEAX@Z"(i8*) +// G32-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*) +// G64-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*) +void UNIQ(use)(ImportAlloc* ptr) { delete[] ptr; } + + +//===----------------------------------------------------------------------===// +// Class member templates +//===----------------------------------------------------------------------===// + +struct MemFunTmpl { + template<typename T> void normalDef() {} + template<typename T> __declspec(dllimport) void importedNormal() {} + template<typename T> static void staticDef() {} + template<typename T> __declspec(dllimport) static void importedStatic() {} +}; + +// Import implicit instantiation of an imported member function template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +USEMF(MemFunTmpl, importedNormal<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv() +USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>) + + +// Import explicit instantiation declaration of an imported member function +// template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>(); +USEMF(MemFunTmpl, importedNormal<ExplicitDecl_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv() +extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>(); +USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>) + + +// Import explicit instantiation definition of an imported member function +// template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +template void MemFunTmpl::importedNormal<ExplicitInst_Imported>(); +USEMF(MemFunTmpl, importedNormal<ExplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv() +template void MemFunTmpl::importedStatic<ExplicitInst_Imported>(); +USE(MemFunTmpl::importedStatic<ExplicitInst_Imported>) + + +// Import specialization of an imported member function template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*) +template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>(); +USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Imported>) + +// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG-FIXME: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +#ifdef MSABI +//template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {} +//USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Def_Imported>) +#endif + +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {} +USEMF(MemFunTmpl, importedNormal<ExplicitSpec_InlineDef_Imported>) + + +// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitSpec_ImportedEEvv() +template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>(); +USE(MemFunTmpl::importedStatic<ExplicitSpec_Imported>) + +// MSC-DAG-FIXME: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"() +#ifdef MSABI +//template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {} +//USE(MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>) +#endif + +// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv() +template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {} +USE(MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>) + + +// Not importing specialization of an imported member function template without +// explicit dllimport. +// M32-DAG: define x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this) +// M64-DAG: define void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this) +// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this) +template<> void MemFunTmpl::importedNormal<ExplicitSpec_NotImported>() {} +USEMF(MemFunTmpl, importedNormal<ExplicitSpec_NotImported>) + +// MSC-DAG: define void @"\01??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: define void @_ZN10MemFunTmpl14importedStaticI24ExplicitSpec_NotImportedEEvv() +template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {} +USE(MemFunTmpl::importedStatic<ExplicitSpec_NotImported>) + + +// Import explicit instantiation declaration of a non-imported member function +// template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>(); +USEMF(MemFunTmpl, normalDef<ExplicitDecl_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv() +extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>(); +USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>) + + +// Import explicit instantiation definition of a non-imported member function +// template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>(); +USEMF(MemFunTmpl, normalDef<ExplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv() +template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>(); +USE(MemFunTmpl::staticDef<ExplicitInst_Imported>) + + +// Import specialization of a non-imported member function template. +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*) +template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>(); +USEMF(MemFunTmpl, normalDef<ExplicitSpec_Imported>) + +// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG-FIXME: declare dllimport void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +#ifdef MSABI +//template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {} +//USEMF(MemFunTmpl, normalDef<ExplicitSpec_Def_Imported>) +#endif + +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {} +USEMF(MemFunTmpl, normalDef<ExplicitSpec_InlineDef_Imported>) + + +// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitSpec_ImportedEEvv() +template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>(); +USE(MemFunTmpl::staticDef<ExplicitSpec_Imported>) + +// MSC-DAG-FIXME: declare dllimport void @"\01??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"() +#ifdef MSABI +//template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {} +//USE(MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>) +#endif + +// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"() +// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv() +template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {} +USE(MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>) + + + +struct MemVarTmpl { + template<typename T> static const int StaticVar = 1; + template<typename T> __declspec(dllimport) static const int ImportedStaticVar = 1; +}; + +// Import implicit instantiation of an imported member variable template. +// MSC-DAG: @"\01??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ImplicitInst_ImportedEE = external dllimport constant i32 +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 +// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32 +extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>; +USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>) + +// An explicit instantiation definition of an imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of an imported member variable template. +// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32 +// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32 +template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Imported>; +USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>) + +// Not importing specialization of a member variable template without explicit +// dllimport. +// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external constant i32 +// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external constant i32 +template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>; +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 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32 +extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>; +USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>) + +// An explicit instantiation definition of a non-imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of a non-imported member variable template. +// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32 +template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Imported>; +USEMV(MemVarTmpl, StaticVar<ExplicitSpec_Imported>) diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp new file mode 100644 index 0000000000000..7ed7dadfe4021 --- /dev/null +++ b/test/CodeGenCXX/dllimport-rtti.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s + +struct __declspec(dllimport) S { + virtual void f(); +} s; +// CHECK-DAG: @"\01??_7S@@6B@" = available_externally dllimport +// CHECK-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr +// CHECK-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr +// CHECK-DAG: @"\01??_R2S@@8" = linkonce_odr +// CHECK-DAG: @"\01??_R3S@@8" = linkonce_odr + +struct U : S { +} u; diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp new file mode 100644 index 0000000000000..59f8f63616196 --- /dev/null +++ b/test/CodeGenCXX/dllimport.cpp @@ -0,0 +1,771 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s -DMSABI | FileCheck --check-prefix=MO1 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s | FileCheck --check-prefix=GO1 %s + +// CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines. +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC2 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU2 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Imported {}; +struct ImplicitInst_NotImported {}; +struct ExplicitDecl_Imported {}; +struct ExplicitInst_Imported {}; +struct ExplicitSpec_Imported {}; +struct ExplicitSpec_Def_Imported {}; +struct ExplicitSpec_InlineDef_Imported {}; +struct ExplicitSpec_NotImported {}; + +#define JOIN2(x, y) x##y +#define JOIN(x, y) JOIN2(x, y) +#define UNIQ(name) JOIN(name, __LINE__) +#define USEVARTYPE(type, var) type UNIQ(use)() { return var; } +#define USEVAR(var) USEVARTYPE(int, var) +#define USE(func) void UNIQ(use)() { func(); } +#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; } +#define USECLASS(class) void UNIQ(USE)() { class x; } +#define USECOPYASSIGN(class) class& (class::*UNIQ(use)())(class&) { return &class::operator=; } +#define USEMOVEASSIGN(class) class& (class::*UNIQ(use)())(class&&) { return &class::operator=; } + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Import declaration. +// MSC-DAG: @"\01?ExternGlobalDecl@@3HA" = external dllimport global i32 +// GNU-DAG: @ExternGlobalDecl = external dllimport global i32 +__declspec(dllimport) extern int ExternGlobalDecl; +USEVAR(ExternGlobalDecl) + +// dllimport implies a declaration. +// MSC-DAG: @"\01?GlobalDecl@@3HA" = external dllimport global i32 +// GNU-DAG: @GlobalDecl = external dllimport global i32 +__declspec(dllimport) int GlobalDecl; +USEVAR(GlobalDecl) + +// Redeclarations +// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = external dllimport global i32 +// GNU-DAG: @GlobalRedecl1 = external dllimport global i32 +__declspec(dllimport) extern int GlobalRedecl1; +__declspec(dllimport) extern int GlobalRedecl1; +USEVAR(GlobalRedecl1) + +// MSC-DAG: @"\01?GlobalRedecl2a@@3HA" = external dllimport global i32 +// GNU-DAG: @GlobalRedecl2a = external dllimport global i32 +__declspec(dllimport) int GlobalRedecl2a; +__declspec(dllimport) int GlobalRedecl2a; +USEVAR(GlobalRedecl2a) + +// M32-DAG: @"\01?GlobalRedecl2b@@3PAHA" = external dllimport global i32* +// M64-DAG: @"\01?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32* +// GNU-DAG: @GlobalRedecl2b = external dllimport global i32* +int *__attribute__((dllimport)) GlobalRedecl2b; +int *__attribute__((dllimport)) GlobalRedecl2b; +USEVARTYPE(int*, GlobalRedecl2b) + +// MSC-DAG: @"\01?GlobalRedecl2c@@3HA" = external dllimport global i32 +// GNU-DAG: @GlobalRedecl2c = external dllimport global i32 +int GlobalRedecl2c __attribute__((dllimport)); +int GlobalRedecl2c __attribute__((dllimport)); +USEVAR(GlobalRedecl2c) + +// NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC +// and drop the dllimport with a warning. +// MSC-DAG: @"\01?GlobalRedecl3@@3HA" = external global i32 +// GNU-DAG: @GlobalRedecl3 = external global i32 +__declspec(dllimport) extern int GlobalRedecl3; + extern int GlobalRedecl3; // dllimport ignored +USEVAR(GlobalRedecl3) + +// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = external dllimport global i32 +// GNU-DAG: @_ZN2ns14ExternalGlobalE = external dllimport global i32 +namespace ns { __declspec(dllimport) int ExternalGlobal; } +USEVAR(ns::ExternalGlobal) + +int f(); +// MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0 +// MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0 +inline int __declspec(dllimport) inlineStaticLocalsFunc() { + static int x = f(); + return x++; +}; +USE(inlineStaticLocalsFunc); + +// The address of a dllimport global cannot be used in constant initialization. +// M32-DAG: @"\01?arr@?0??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer +// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer +int *initializationFunc() { + static int *const arr[] = {&ExternGlobalDecl}; + return arr[0]; +} +USE(initializationFunc); + + +//===----------------------------------------------------------------------===// +// Variable templates +//===----------------------------------------------------------------------===// + +// Import declaration. +// MSC-DAG: @"\01??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z17ExternVarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32 +template<typename T> __declspec(dllimport) extern int ExternVarTmplDecl; +USEVAR(ExternVarTmplDecl<ImplicitInst_Imported>) + +// dllimport implies a declaration. +// MSC-DAG: @"\01??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z11VarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32 +template<typename T> __declspec(dllimport) int VarTmplDecl; +USEVAR(VarTmplDecl<ImplicitInst_Imported>) + +// Redeclarations +// MSC-DAG: @"\01??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z14VarTmplRedecl1I21ImplicitInst_ImportedE = external dllimport global i32 +template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; +template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; +USEVAR(VarTmplRedecl1<ImplicitInst_Imported>) + +// MSC-DAG: @"\01??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z14VarTmplRedecl2I21ImplicitInst_ImportedE = external dllimport global i32 +template<typename T> __declspec(dllimport) int VarTmplRedecl2; +template<typename T> __declspec(dllimport) int VarTmplRedecl2; +USEVAR(VarTmplRedecl2<ImplicitInst_Imported>) + +// MSC-DAG: @"\01??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external global i32 +// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external global i32 +template<typename T> __declspec(dllimport) extern int VarTmplRedecl3; +template<typename T> extern int VarTmplRedecl3; // dllimport ignored +USEVAR(VarTmplRedecl3<ImplicitInst_Imported>) + + +// MSC-DAG: @"\01??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32 +// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ImplicitInst_ImportedEE = external dllimport global i32 +namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; } +USEVAR(ns::ExternalVarTmpl<ImplicitInst_Imported>) + + +template<typename T> int VarTmpl; +template<typename T> __declspec(dllimport) int ImportedVarTmpl; + +// Import implicit instantiation of an imported variable template. +// MSC-DAG: @"\01??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z15ImportedVarTmplI21ImplicitInst_ImportedE = external dllimport global i32 +USEVAR(ImportedVarTmpl<ImplicitInst_Imported>) + +// Import explicit instantiation declaration of an imported variable template. +// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitDecl_ImportedE = external dllimport global i32 +extern template int ImportedVarTmpl<ExplicitDecl_Imported>; +USEVAR(ImportedVarTmpl<ExplicitDecl_Imported>) + +// An explicit instantiation definition of an imported variable template cannot +// be imported because the template must be defined which is illegal. + +// Import specialization of an imported variable template. +// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitSpec_ImportedE = external dllimport global i32 +template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Imported>; +USEVAR(ImportedVarTmpl<ExplicitSpec_Imported>) + +// Not importing specialization of an imported variable template without +// explicit dllimport. +// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = global i32 0, align 4 +// GNU-DAG: @_Z15ImportedVarTmplI24ExplicitSpec_NotImportedE = global i32 0, align 4 +template<> int ImportedVarTmpl<ExplicitSpec_NotImported>; +USEVAR(ImportedVarTmpl<ExplicitSpec_NotImported>) + +// Import explicit instantiation declaration of a non-imported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ImportedE = external dllimport global i32 +extern template __declspec(dllimport) int VarTmpl<ExplicitDecl_Imported>; +USEVAR(VarTmpl<ExplicitDecl_Imported>) + +// Import explicit instantiation definition of a non-imported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ImportedE = external dllimport global i32 +template __declspec(dllimport) int VarTmpl<ExplicitInst_Imported>; +USEVAR(VarTmpl<ExplicitInst_Imported>) + +// Import specialization of a non-imported variable template. +// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32 +// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ImportedE = external dllimport global i32 +template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Imported>; +USEVAR(VarTmpl<ExplicitSpec_Imported>) + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Import function declaration. +// MSC-DAG: declare dllimport void @"\01?decl@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z4declv() +__declspec(dllimport) void decl(); +USE(decl) + +// extern "C" +// MSC-DAG: declare dllimport void @externC() +// GNU-DAG: declare dllimport void @externC() +extern "C" __declspec(dllimport) void externC(); +USE(externC) + +// Import inline function. +// MSC-DAG: declare dllimport void @"\01?inlineFunc@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z10inlineFuncv() +// MO1-DAG: define available_externally dllimport void @"\01?inlineFunc@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z10inlineFuncv() +__declspec(dllimport) inline void inlineFunc() {} +USE(inlineFunc) + +// MSC-DAG: declare dllimport void @"\01?inlineDecl@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z10inlineDeclv() +// MO1-DAG: define available_externally dllimport void @"\01?inlineDecl@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z10inlineDeclv() +__declspec(dllimport) inline void inlineDecl(); + void inlineDecl() {} +USE(inlineDecl) + +// MSC-DAG: declare dllimport void @"\01?inlineDef@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z9inlineDefv() +// MO1-DAG: define available_externally dllimport void @"\01?inlineDef@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z9inlineDefv() +__declspec(dllimport) void inlineDef(); + inline void inlineDef() {} +USE(inlineDef) + +// inline attributes +// MSC-DAG: declare dllimport void @"\01?noinline@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z8noinlinev() +__declspec(dllimport) __attribute__((noinline)) inline void noinline() {} +USE(noinline) + +// MSC2-NOT: @"\01?alwaysInline@@YAXXZ"() +// GNU2-NOT: @_Z12alwaysInlinev() +__declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {} +USE(alwaysInline) + +// Redeclarations +// MSC-DAG: declare dllimport void @"\01?redecl1@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z7redecl1v() +__declspec(dllimport) void redecl1(); +__declspec(dllimport) void redecl1(); +USE(redecl1) + +// NB: MSC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC +// and drop the dllimport with a warning. +// MSC-DAG: declare void @"\01?redecl2@@YAXXZ"() +// GNU-DAG: declare void @_Z7redecl2v() +__declspec(dllimport) void redecl2(); + void redecl2(); +USE(redecl2) + +// MSC-DAG: define void @"\01?redecl3@@YAXXZ"() +// GNU-DAG: define void @_Z7redecl3v() +__declspec(dllimport) void redecl3(); + void redecl3() {} // dllimport ignored +USE(redecl3) + + +// Friend functions +// MSC-DAG: declare dllimport void @"\01?friend1@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z7friend1v() +// MSC-DAG: declare void @"\01?friend2@@YAXXZ"() +// GNU-DAG: declare void @_Z7friend2v() +// MSC-DAG: define void @"\01?friend3@@YAXXZ"() +// GNU-DAG: define void @_Z7friend3v() +struct FuncFriend { + friend __declspec(dllimport) void friend1(); + friend __declspec(dllimport) void friend2(); + friend __declspec(dllimport) void friend3(); +}; +__declspec(dllimport) void friend1(); + void friend2(); // dllimport ignored + void friend3() {} // dllimport ignored +USE(friend1) +USE(friend2) +USE(friend3) + +// Implicit declarations can be redeclared with dllimport. +// MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"( +// GNU-DAG: declare dllimport noalias i8* @_Znw{{[yj]}}( +__declspec(dllimport) void* operator new(__SIZE_TYPE__ n); +void UNIQ(use)() { ::operator new(42); } + +// MSC-DAG: declare dllimport void @"\01?externalFunc@ns@@YAXXZ"() +// GNU-DAG: declare dllimport void @_ZN2ns12externalFuncEv() +namespace ns { __declspec(dllimport) void externalFunc(); } +USE(ns::externalFunc) + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Import function template declaration. +// MSC-DAG: declare dllimport void @"\01??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z12funcTmplDeclI21ImplicitInst_ImportedEvv() +template<typename T> __declspec(dllimport) void funcTmplDecl(); +USE(funcTmplDecl<ImplicitInst_Imported>) + +// Function template definitions cannot be imported. + +// Import inline function template. +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() +template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {} +USE(inlineFuncTmpl1<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() +template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {} +USE(inlineFuncTmpl2<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() +template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} +USE(inlineFuncTmplDecl<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() +template<typename T> __declspec(dllimport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} +USE(inlineFuncTmplDef<ImplicitInst_Imported>) + + +// Redeclarations +// MSC-DAG: declare dllimport void @"\01??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z15funcTmplRedecl1I21ImplicitInst_ImportedEvv() +template<typename T> __declspec(dllimport) void funcTmplRedecl1(); +template<typename T> __declspec(dllimport) void funcTmplRedecl1(); +USE(funcTmplRedecl1<ImplicitInst_Imported>) + +// MSC-DAG: declare void @"\01??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"() +// GNU-DAG: declare void @_Z15funcTmplRedecl2I24ImplicitInst_NotImportedEvv() +template<typename T> __declspec(dllimport) void funcTmplRedecl2(); +template<typename T> void funcTmplRedecl2(); // dllimport ignored +USE(funcTmplRedecl2<ImplicitInst_NotImported>) + +// MSC-DAG: define linkonce_odr void @"\01??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"() +// GNU-DAG: define linkonce_odr void @_Z15funcTmplRedecl3I24ImplicitInst_NotImportedEvv() +template<typename T> __declspec(dllimport) void funcTmplRedecl3(); +template<typename T> void funcTmplRedecl3() {} // dllimport ignored +USE(funcTmplRedecl3<ImplicitInst_NotImported>) + + +// Function template friends +// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z15funcTmplFriend1I21ImplicitInst_ImportedEvv() +// MSC-DAG: declare void @"\01??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"() +// GNU-DAG: declare void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv() +// MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"() +// GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv() +// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv() +struct FuncTmplFriend { + template<typename T> friend __declspec(dllimport) void funcTmplFriend1(); + template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); + template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); + template<typename T> friend __declspec(dllimport) inline void funcTmplFriend4(); +}; +template<typename T> __declspec(dllimport) void funcTmplFriend1(); +template<typename T> void funcTmplFriend2(); // dllimport ignored +template<typename T> void funcTmplFriend3() {} // dllimport ignored +template<typename T> inline void funcTmplFriend4() {} +USE(funcTmplFriend1<ImplicitInst_Imported>) +USE(funcTmplFriend2<ImplicitInst_NotImported>) +USE(funcTmplFriend3<ImplicitInst_NotImported>) +USE(funcTmplFriend4<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"() +// GNU-DAG: declare dllimport void @_ZN2ns16externalFuncTmplI21ImplicitInst_ImportedEEvv() +namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); } +USE(ns::externalFuncTmpl<ImplicitInst_Imported>) + + +template<typename T> void funcTmpl() {} +template<typename T> inline void inlineFuncTmpl() {} +template<typename T> __declspec(dllimport) void importedFuncTmplDecl(); +template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {} + +// Import implicit instantiation of an imported function template. +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ImplicitInst_ImportedEvv() +USE(importedFuncTmplDecl<ImplicitInst_Imported>) + +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() +USE(importedFuncTmpl<ImplicitInst_Imported>) + +// Import explicit instantiation declaration of an imported function template. +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() +extern template void importedFuncTmpl<ExplicitDecl_Imported>(); +USE(importedFuncTmpl<ExplicitDecl_Imported>) + +// Import explicit instantiation definition of an imported function template. +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() +template void importedFuncTmpl<ExplicitInst_Imported>(); +USE(importedFuncTmpl<ExplicitInst_Imported>) + + +// Import specialization of an imported function template. +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ExplicitSpec_ImportedEvv() +template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Imported>(); +USE(importedFuncTmplDecl<ExplicitSpec_Imported>) + +// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +#ifdef MSABI +//template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Def_Imported>() {} +//USE(importedFuncTmplDecl<ExplicitSpec_Def_Imported>) +#endif + +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() +template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {} +USE(importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>) + + +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitSpec_ImportedEvv() +template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>(); +USE(importedFuncTmpl<ExplicitSpec_Imported>) + +// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +#ifdef MSABI +//template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} +//USE(importedFuncTmpl<ExplicitSpec_Def_Imported>) +#endif + +// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() +template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} +USE(importedFuncTmpl<ExplicitSpec_InlineDef_Imported>) + + +// Not importing specialization of an imported function template without +// explicit dllimport. +// MSC-DAG: define void @"\01??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"() +// GNU-DAG: define void @_Z16importedFuncTmplI24ExplicitSpec_NotImportedEvv() +template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {} +USE(importedFuncTmpl<ExplicitSpec_NotImported>) + + +// Import explicit instantiation declaration of a non-imported function template. +// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"() +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitDecl_ImportedEvv() +// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() +extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>(); +extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>(); +USE(funcTmpl<ExplicitDecl_Imported>) +USE(inlineFuncTmpl<ExplicitDecl_Imported>) + + +// Import explicit instantiation definition of a non-imported function template. +// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"() +// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv() +// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() +// MO1-DAG: define available_externally 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 available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() +template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>(); +template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>(); +USE(funcTmpl<ExplicitInst_Imported>) +USE(inlineFuncTmpl<ExplicitInst_Imported>) + + +// Import specialization of a non-imported function template. +// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitSpec_ImportedEvv() +template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>(); +USE(funcTmpl<ExplicitSpec_Imported>) + +// MSC-DAG-FIXME: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"() +#ifdef MSABI +//template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} +//USE(funcTmpl<ExplicitSpec_Def_Imported>) +#endif + +// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() +// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() +template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} +USE(funcTmpl<ExplicitSpec_InlineDef_Imported>) + + + +//===----------------------------------------------------------------------===// +// Classes +//===----------------------------------------------------------------------===// + +struct __declspec(dllimport) T { + void a() {} + // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@T@@QAEXXZ" + + static int b; + // MO1-DAG: @"\01?b@T@@2HA" = external dllimport global i32 + + T& operator=(T&) = default; + // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@AAU0@@Z" + + T& operator=(T&&) = default; + // Note: Don't mark inline move operators dllimport because current MSVC versions don't export them. + // MO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z" +}; +USEMEMFUNC(T, a) +USEVAR(T::b) +USECOPYASSIGN(T) +USEMOVEASSIGN(T) + +template <typename T> struct __declspec(dllimport) U { void foo() {} }; +// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ" +struct __declspec(dllimport) V : public U<int> { }; +USEMEMFUNC(V, foo) + +struct __declspec(dllimport) W { virtual void foo() {} }; +USECLASS(W) +// vftable: +// MO1-DAG: @"\01??_7W@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] +// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] + +struct __declspec(dllimport) KeyFuncClass { + constexpr KeyFuncClass() {} + virtual void foo(); +}; +constexpr KeyFuncClass keyFuncClassVar; +// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*] + +struct __declspec(dllimport) X : public virtual W {}; +USECLASS(X) +// vbtable: +// MO1-DAG: @"\01??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] + +struct __declspec(dllimport) Y { + int x; +}; + +struct __declspec(dllimport) Z { virtual ~Z() {} }; +USECLASS(Z) +// User-defined dtor: +// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1Z@@UAE@XZ" + +namespace DontUseDtorAlias { + struct __declspec(dllimport) A { ~A(); }; + struct __declspec(dllimport) B : A { ~B(); }; + inline A::~A() { } + inline B::~B() { } + // Emit a real definition of B's constructor; don't alias it to A's. + // MO1-DAG: available_externally dllimport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ" + USECLASS(B) +} + +namespace Vtordisp { + // Don't dllimport the vtordisp. + // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@D@Vtordisp@@$4PPPPPPPM@A@AEXXZ" + + class Base { + virtual void f() {} + }; + template <typename T> + class __declspec(dllimport) C : virtual public Base { + public: + C() {} + virtual void f() {} + }; + template class C<char>; +} + +namespace ClassTemplateStaticDef { + // Regular template static field: + template <typename T> struct __declspec(dllimport) S { + static int x; + }; + template <typename T> int S<T>::x; + // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = available_externally dllimport global i32 0 + int f() { return S<int>::x; } + + // Partial class template specialization static field: + template <typename A> struct T; + template <typename A> struct __declspec(dllimport) T<A*> { + static int x; + }; + template <typename A> int T<A*>::x; + // GNU-DAG: @_ZN22ClassTemplateStaticDef1TIPvE1xE = available_externally dllimport global i32 0 + int g() { return T<void*>::x; } +} + +namespace PR19933 { +// Don't dynamically initialize dllimport vars. +// MSC2-NOT: @llvm.global_ctors +// GNU2-NOT: @llvm.global_ctors + + struct NonPOD { NonPOD(); }; + template <typename T> struct A { static NonPOD x; }; + template <typename T> NonPOD A<T>::x; + template struct __declspec(dllimport) A<int>; + // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = available_externally dllimport global %"struct.PR19933::NonPOD" zeroinitializer + + int f(); + template <typename T> struct B { static int x; }; + template <typename T> int B<T>::x = f(); + template struct __declspec(dllimport) B<int>; + // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = available_externally dllimport global i32 0 + + constexpr int g() { return 42; } + template <typename T> struct C { static int x; }; + template <typename T> int C<T>::x = g(); + template struct __declspec(dllimport) C<int>; + // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = available_externally dllimport global i32 42 + + template <int I> struct D { static int x, y; }; + template <int I> int D<I>::x = I + 1; + template <int I> int D<I>::y = I + f(); + template struct __declspec(dllimport) D<42>; + // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 43 + // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 0 +} + +// MS ignores DLL attributes on partial specializations. +template <typename T> struct PartiallySpecializedClassTemplate {}; +template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f() {} }; +USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f); +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv + +template <typename T> struct ExplicitlySpecializedClassTemplate {}; +template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f() {} }; +USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f); +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template <typename T> struct ClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; + +template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; +template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; + +template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; +template struct ExplicitlyInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; + + +// MS: ClassTemplate<int> gets imported. +struct __declspec(dllimport) DerivedFromTemplate : public ClassTemplate<int> {}; +USEMEMFUNC(ClassTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv + +// ImportedTemplate is explicitly imported. +struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; +USEMEMFUNC(ImportedClassTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv + +// ExportedTemplate is explicitly exported. +struct __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; +USEMEMFUNC(ExportedClassTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv + +// Base class already instantiated without attribute. +struct DerivedFromTemplateD : public ClassTemplate<double> {}; +struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; +USEMEMFUNC(ClassTemplate<double>, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv + +// MS: Base class already instantiated with dfferent attribute. +struct __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {}; +struct __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; +USEMEMFUNC(ClassTemplate<bool>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv + +// Base class already specialized without dll attribute. +struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv + +// Base class alredy specialized with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv + +// Base class already specialized with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; +USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv + +// Base class already instantiated without dll attribute. +struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func) +// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; +USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv + +// MS: A dll attribute propagates through multiple levels of instantiation. +template <typename T> struct TopClass { void func() {} }; +template <typename T> struct MiddleClass : public TopClass<T> { }; +struct __declspec(dllimport) BottomClass : public MiddleClass<int> { }; +USEMEMFUNC(TopClass<int>, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp new file mode 100644 index 0000000000000..65bfa22ac6219 --- /dev/null +++ b/test/CodeGenCXX/duplicate-mangled-name.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify + +// rdar://15522601 +class MyClass { + static void meth(); +}; +void MyClass::meth() { } +extern "C" { + void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} +} diff --git a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp index 0e26de5bcf8be..cde03a3f4e09d 100644 --- a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp +++ b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -triple %itanium_abi_triple -o - | FileCheck %s // expected-no-diagnostics struct A { diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index 2a61e61bb8184..cb07697fb33f1 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -34,7 +34,7 @@ void test2() { // CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32 // CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16) // CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] -// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] @d2) +// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] dereferenceable({{[0-9]+}}) @d2) // CHECK-NEXT: to label %[[CONT:.*]] unwind label %{{.*}} // : [[CONT]]: (can't check this in Release-Asserts builds) // CHECK: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTI7test2_D to i8*), i8* null) [[NR]] @@ -184,9 +184,6 @@ namespace test9 { struct A { A(); }; - // CHECK-LABEL: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr - // CHECK: call void @_ZN5test91AC2Ev - // CHECK-NEXT: ret void // CHECK-LABEL: define void @_ZN5test91AC2Ev(%"struct.test9::A"* %this) unnamed_addr A::A() try { @@ -199,6 +196,10 @@ namespace test9 { // CHECK: call i8* @__cxa_begin_catch // CHECK: invoke void @_ZN5test96opaqueEv() // CHECK: invoke void @__cxa_rethrow() + + // CHECK-LABEL: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr + // CHECK: call void @_ZN5test91AC2Ev + // CHECK-NEXT: ret void opaque(); } } @@ -427,7 +428,7 @@ namespace test16 { // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[EXN]] to [[B:%.*]]* // CHECK-NEXT: invoke void @_ZN6test161AC1Ev([[A]]* [[TEMP]]) // CHECK: store i1 true, i1* [[TEMP_ACTIVE]] - // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* [[TEMP]]) + // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* dereferenceable({{[0-9]+}}) [[TEMP]]) // CHECK: store i1 false, i1* [[EXN_ACTIVE]] // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXN]], diff --git a/test/CodeGenCXX/elide-call-reference.cpp b/test/CodeGenCXX/elide-call-reference.cpp index 55d30e24c102a..0ce856f0c2236 100644 --- a/test/CodeGenCXX/elide-call-reference.cpp +++ b/test/CodeGenCXX/elide-call-reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // PR5695 struct A { A(const A&); ~A(); }; diff --git a/test/CodeGenCXX/empty-nontrivially-copyable.cpp b/test/CodeGenCXX/empty-nontrivially-copyable.cpp index 9ee3281505ec3..a0977a7e690a6 100644 --- a/test/CodeGenCXX/empty-nontrivially-copyable.cpp +++ b/test/CodeGenCXX/empty-nontrivially-copyable.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple armv7-apple-ios -x c++ -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios -x c++ -emit-llvm -o - %s | FileCheck %s // According to the Itanium ABI (3.1.1), types with non-trivial copy // constructors passed by value should be passed indirectly, with the caller @@ -18,7 +19,7 @@ bool foo(Empty e) { } void caller(Empty &e) { -// CHECK: @_Z6callerR5Empty(%struct.Empty* %e) +// CHECK: @_Z6callerR5Empty(%struct.Empty* dereferenceable({{[0-9]+}}) %e) // CHECK: call {{.*}} @_ZN5EmptyC1ERKS_(%struct.Empty* [[NEWTMP:%.*]], %struct.Empty* // CHECK: call {{.*}} @_Z3foo5Empty(%struct.Empty* [[NEWTMP]]) foo(e); diff --git a/test/CodeGenCXX/enable_if.cpp b/test/CodeGenCXX/enable_if.cpp new file mode 100644 index 0000000000000..00c55c774909e --- /dev/null +++ b/test/CodeGenCXX/enable_if.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu| FileCheck %s +// Test itanium mangling for attribute enable_if + +// CHECK: _Z5test1Ua9enable_ifIXeqfL0p_Li1EEEi +void test1(int i) __attribute__((enable_if(i == 1, ""))) {} + +void ext(); +// CHECK: _Z5test2Ua9enable_ifIXneadL_Z3extvELi0EEEi +void test2(int i) __attribute__((enable_if(&ext != 0, ""))) {} + +// CHECK: _Z5test3Ua9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEii +void test3(int i, int j) __attribute__((enable_if(i == 1, ""), enable_if(j == 2, ""))) {} + +// CHECK: _ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi +template <typename T> +class test4 { + virtual void f(int i, int j) __attribute__((enable_if(i == 1, ""))) __attribute__((enable_if(j == 2, ""))); +}; + +template class test4<double>; diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp index 902d6ac2973a8..e1ef4f1ddad78 100644 --- a/test/CodeGenCXX/exceptions-no-rtti.cpp +++ b/test/CodeGenCXX/exceptions-no-rtti.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fno-rtti -fcxx-exceptions -fexceptions %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// CHECK: @_ZTIN5test11AE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTIN5test11BE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTIN5test11CE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTIN5test11DE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTIPN5test11DE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN5test11DE +// CHECK: @_ZTIN5test11AE = linkonce_odr constant +// CHECK: @_ZTIN5test11BE = linkonce_odr constant +// CHECK: @_ZTIN5test11CE = linkonce_odr constant +// CHECK: @_ZTIN5test11DE = linkonce_odr constant +// CHECK: @_ZTIPN5test11DE = linkonce_odr constant {{.*}} @_ZTIN5test11DE // PR6974: this shouldn't crash namespace test0 { diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index d37e6109db4ae..5016e9a794ae4 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -279,7 +279,7 @@ namespace test5 { // CHECK-NEXT: [[ADJ:%.*]] = call i8* @__cxa_get_exception_ptr(i8* [[EXN]]) // CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[ADJ]] to [[A_T]]* // CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]]) - // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]]) + // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* dereferenceable({{[0-9]+}}) [[SRC]], [[T_T]]* dereferenceable({{[0-9]+}}) [[T]]) // CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]]) // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]] // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]]) diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 6a4fd822122fc..5bd06784cfabb 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT // This check logically is attached to 'template int S<int>::i;' below. // CHECK: @_ZN1SIiE1iE = weak_odr global i32 @@ -16,6 +17,79 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const { // CHECK-LABEL: define weak_odr i32 @_ZNK4plusIillEclERKiRKl template struct plus<int, long, long>; +namespace EarlyInstantiation { + // Check that we emit definitions if we instantiate a function definition before + // it gets explicitly instantiatied. + template<typename T> struct S { + constexpr int constexpr_function() { return 0; } + auto deduced_return_type() { return 0; } + }; + + // From an implicit instantiation. + constexpr int a = S<char>().constexpr_function(); + int b = S<char>().deduced_return_type(); + + // From an explicit instantiation declaration. + extern template struct S<int>; + constexpr int c = S<int>().constexpr_function(); + int d = S<int>().deduced_return_type(); + + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE18constexpr_functionEv( + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE19deduced_return_typeEv( + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE18constexpr_functionEv( + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE19deduced_return_typeEv( + template struct S<char>; + template struct S<int>; + + template<typename T> constexpr int constexpr_function() { return 0; } + template<typename T> auto deduced_return_type() { return 0; } + + // From an implicit instantiation. + constexpr int e = constexpr_function<char>(); + int f = deduced_return_type<char>(); + + // From an explicit instantiation declaration. + extern template int constexpr_function<int>(); + extern template auto deduced_return_type<int>(); + constexpr int g = constexpr_function<int>(); + int h = deduced_return_type<int>(); + + // The FIXMEs below are for PR19551. + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIcEEiv( + // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIcEEiv( + // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIiEEiv( + // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIiEEiv( + template int constexpr_function<char>(); + // FIXME template auto deduced_return_type<char>(); + template int constexpr_function<int>(); + // FIXME template auto deduced_return_type<int>(); +} + +namespace LateInstantiation { + // Check that we downgrade the linkage to available_externally if we see an + // explicit instantiation declaration after the function template is + // instantiated. + template<typename T> struct S { constexpr int f() { return 0; } }; + template<typename T> constexpr int f() { return 0; } + + // Trigger eager instantiation of the function definitions. + int a, b = S<char>().f() + f<char>() + a; + int c, d = S<int>().f() + f<int>() + a; + + // Don't allow some of those definitions to be emitted. + extern template struct S<int>; + extern template int f<int>(); + + // Check that we declare, define, or provide an available-externally + // definition as appropriate. + // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1SIcE1fEv( + // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1fIcEEiv( + // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1SIiE1fEv( + // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1fIiEEiv( + // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1SIiE1fEv( + // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1fIiEEiv( +} + // Check that we emit definitions from explicit instantiations even when they // occur prior to the definition itself. template <typename T> struct S { diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp index 5899b9348c5a3..fefb216ea1c0e 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -1,18 +1,21 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s namespace foo { -// CHECK-NOT: @a = global i32 +// CHECK-NOT: @a = global extern "C" int a; -// CHECK-NOT: @_ZN3foo1bE = global i32 +// CHECK-NOT: @_ZN3foo1bE = global extern int b; -// CHECK: @_ZN3foo1cE = global i32 +// CHECK: @_ZN3foo1cE = global int c = 5; // CHECK-NOT: @_ZN3foo1dE extern "C" struct d; +// CHECK-NOT: should_not_appear +extern "C++" int should_not_appear; + } namespace test1 { @@ -63,3 +66,10 @@ extern "C" { // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal } + +namespace PR19411 { + struct A { void f(); }; + extern "C" void A::f() { void g(); g(); } + // CHECK-LABEL: @_ZN7PR194111A1fEv( + // CHECK: call void @g() +} diff --git a/test/CodeGenCXX/fastcall.cpp b/test/CodeGenCXX/fastcall.cpp index 0326ce53bc4a8..0820324558eea 100644 --- a/test/CodeGenCXX/fastcall.cpp +++ b/test/CodeGenCXX/fastcall.cpp @@ -3,7 +3,7 @@ void __attribute__((fastcall)) foo1(int &y); void bar1(int &y) { // CHECK-LABEL: define void @_Z4bar1Ri - // CHECK: call x86_fastcallcc void @_Z4foo1Ri(i32* inreg % + // CHECK: call x86_fastcallcc void @_Z4foo1Ri(i32* inreg dereferenceable({{[0-9]+}}) % foo1(y); } diff --git a/test/CodeGenCXX/field-access-debug-info.cpp b/test/CodeGenCXX/field-access-debug-info.cpp index fd899ed71e1c8..aed4ee5f3a776 100644 --- a/test/CodeGenCXX/field-access-debug-info.cpp +++ b/test/CodeGenCXX/field-access-debug-info.cpp @@ -1,8 +1,7 @@ -// RUN: %clang_cc1 -g -S -masm-verbose -o - %s | FileCheck %s +// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s -// CHECK: abbrev_begin: -// CHECK: DW_AT_accessibility -// CHECK-NEXT: DW_FORM_data1 +// CHECK: [ DW_TAG_member ] [p] [{{[^]]*}}] [from int] +// CHECK: [ DW_TAG_member ] [pr] [{{[^]]*}}] [private] [from int] class A { public: diff --git a/test/CodeGenCXX/flatten.cpp b/test/CodeGenCXX/flatten.cpp new file mode 100644 index 0000000000000..9e0f67f78984c --- /dev/null +++ b/test/CodeGenCXX/flatten.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s + +void f(void) {} + +[[gnu::flatten]] +// CHECK: define void @_Z1gv() +void g(void) { + // CHECK-NOT: call {{.*}} @_Z1fv + f(); +} diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp new file mode 100644 index 0000000000000..684a796c19058 --- /dev/null +++ b/test/CodeGenCXX/funcsig.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s + +// Similar to predefined-expr.cpp, but not as exhaustive, since it's basically +// equivalent to __PRETTY_FUNCTION__. + +extern "C" int printf(const char *, ...); + +void freeFunc(int *, char) { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" + +struct TopLevelClass { + void topLevelMethod(int *, char); +}; +void TopLevelClass::topLevelMethod(int *, char) { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" + +namespace NS { +struct NamespacedClass { + void namespacedMethod(int *, char); +}; +void NamespacedClass::namespacedMethod(int *, char) { + printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); +} +// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" +} diff --git a/test/CodeGenCXX/function-template-explicit-specialization.cpp b/test/CodeGenCXX/function-template-explicit-specialization.cpp index 5d26dcd61cf03..8ff0655697572 100644 --- a/test/CodeGenCXX/function-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/function-template-explicit-specialization.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s template<typename T> void a(T); template<> void a(int) {} diff --git a/test/CodeGenCXX/function-template-specialization.cpp b/test/CodeGenCXX/function-template-specialization.cpp index 4a79fb1d6747b..eb099df14d002 100644 --- a/test/CodeGenCXX/function-template-specialization.cpp +++ b/test/CodeGenCXX/function-template-specialization.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s template<typename T, typename U> T* next(T* ptr, const U& diff); diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp index 6ebc13953f678..0397851e0d922 100644 --- a/test/CodeGenCXX/global-array-destruction.cpp +++ b/test/CodeGenCXX/global-array-destruction.cpp @@ -56,7 +56,7 @@ using U = T[2][3]; U &&u = U{ {{1.0, 2}, {3.0, 4}, {5.0, 6}}, {{7.0, 8}, {9.0, 10}, {11.0, 12}} }; // CHECK: call {{.*}} @__cxa_atexit -// CHECK: getelementptr inbounds ({{.*}}* getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u, i32 0, i32 0, i32 0), i64 6) +// CHECK: getelementptr inbounds ({{.*}}* getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u_, i32 0, i32 0, i32 0), i64 6) // CHECK: call void @_ZN1TD1Ev -// CHECK: icmp eq {{.*}} @_ZGR1u +// CHECK: icmp eq {{.*}} @_ZGR1u_ // CHECK: br i1 {{.*}} diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 69631c278905c..9c5b03a928456 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -12,7 +12,7 @@ struct C { void *field; }; struct D { ~D(); }; -// CHECK: @__dso_handle = external unnamed_addr global i8 +// CHECK: @__dso_handle = external global i8 // CHECK: @c = global %struct.C zeroinitializer, align 8 // It's okay if we ever implement the IR-generation optimization to remove this. @@ -195,11 +195,11 @@ namespace test7 { // CHECK-NEXT: sub // CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1yE -// CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: define internal void @_GLOBAL__sub_I_global_init.cpp() section "__TEXT,__StaticInit,regular,pure_instructions" { // CHECK: call void [[TEST1_Y_INIT]] // CHECK: call void [[TEST1_Z_INIT]] // rdar://problem/8090834: this should be nounwind -// CHECK-NOEXC: define internal void @_GLOBAL__I_a() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { // CHECK-NOEXC: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenCXX/global-llvm-constant.cpp b/test/CodeGenCXX/global-llvm-constant.cpp index 2bd43b99a5d94..55933eecfc3ee 100644 --- a/test/CodeGenCXX/global-llvm-constant.cpp +++ b/test/CodeGenCXX/global-llvm-constant.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s struct A { A() { x = 10; } diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp new file mode 100644 index 0000000000000..eb39aec94d485 --- /dev/null +++ b/test/CodeGenCXX/globalinit-loc.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// rdar://problem/14985269. +// +// Verify that the global init helper function does not get associated +// with any source location. +// +// CHECK: define internal void @_GLOBAL__sub_I_globalinit_loc.cpp +// CHECK: !dbg ![[DBG:.*]] +// CHECK: "_GLOBAL__sub_I_globalinit_loc.cpp", i32 0, {{.*}}, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def] +// CHECK: ![[DBG]] = metadata !{i32 0, i32 0, +# 99 "someheader.h" +class A { +public: + A(); + int foo() { return 0; } +}; +# 5 "main.cpp" +A a; + +int f() { + return a.foo(); +} + diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp index 904f95fb22be1..c1a0eeccf8113 100644 --- a/test/CodeGenCXX/goto.cpp +++ b/test/CodeGenCXX/goto.cpp @@ -22,7 +22,7 @@ namespace test0 { // CHECK: store i1 true, i1* [[CLEANUPACTIVE]] // CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]* // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]]) - // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* [[TMP]]) + // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* dereferenceable({{[0-9]+}}) [[TMP]]) // CHECK: store i1 false, i1* [[CLEANUPACTIVE]] // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[TMP]]) A y; diff --git a/test/CodeGenCXX/implicit-copy-assign-operator.cpp b/test/CodeGenCXX/implicit-copy-assign-operator.cpp index 267402122f827..fded035822ab2 100644 --- a/test/CodeGenCXX/implicit-copy-assign-operator.cpp +++ b/test/CodeGenCXX/implicit-copy-assign-operator.cpp @@ -40,7 +40,7 @@ void test_D(D d1, D d2) { d1 = d2; } -// CHECK-LABEL: define linkonce_odr %struct.D* @_ZN1DaSERS_ +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.D* @_ZN1DaSERS_ // CHECK: {{call.*_ZN1AaSERS_}} // CHECK: {{call.*_ZN1BaSERS_}} // CHECK: {{call.*_ZN1CaSERKS_}} @@ -53,4 +53,3 @@ void test_D(D d1, D d2) { // CHECK: call void @_ZN11CopyByValueC1ERKS_ // CHECK: {{call.*_ZN11CopyByValueaSES_}} // CHECK: ret - diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp index bb04318e73076..d0224131c4da0 100644 --- a/test/CodeGenCXX/implicit-copy-constructor.cpp +++ b/test/CodeGenCXX/implicit-copy-constructor.cpp @@ -40,7 +40,7 @@ void f(D d) { D d2(d); } -// CHECK-LABEL: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr +// CHECK-LABEL: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D* dereferenceable({{[0-9]+}})) unnamed_addr // CHECK: call void @_ZN1AC1Ev // CHECK: call void @_ZN1CC2ERS_1A // CHECK: call void @_ZN1AD1Ev diff --git a/test/CodeGenCXX/implicit-instantiation-1.cpp b/test/CodeGenCXX/implicit-instantiation-1.cpp index bf6a14150892a..c3c49c3218b32 100644 --- a/test/CodeGenCXX/implicit-instantiation-1.cpp +++ b/test/CodeGenCXX/implicit-instantiation-1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o %t +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o %t template<typename T> struct X { diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp index c99a20c730e42..9394137e64144 100644 --- a/test/CodeGenCXX/inheriting-constructor.cpp +++ b/test/CodeGenCXX/inheriting-constructor.cpp @@ -11,9 +11,9 @@ struct C { template<typename T> C(T); }; struct D : C { using C::C; }; D d(123); -// CHECK-LABEL: define void @_ZN1BD0Ev -// CHECK-LABEL: define void @_ZN1BD1Ev // CHECK-LABEL: define void @_ZN1BD2Ev +// CHECK-LABEL: define void @_ZN1BD1Ev +// CHECK-LABEL: define void @_ZN1BD0Ev // CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ei( // CHECK: call void @_ZN1BC2Ei( diff --git a/test/CodeGenCXX/init-priority-attr.cpp b/test/CodeGenCXX/init-priority-attr.cpp index ef9343ceade99..ff155d07ca2ee 100644 --- a/test/CodeGenCXX/init-priority-attr.cpp +++ b/test/CodeGenCXX/init-priority-attr.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// PR +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -O2 -emit-llvm -o - | FileCheck %s +// PR11480 void foo(int); @@ -27,18 +27,24 @@ public: A C::a = A(); -// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 200, void ()* @_GLOBAL__I_000200 }, { i32, void ()* } { i32 300, void ()* @_GLOBAL__I_000300 }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] +// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] +// CHECK: [{ i32, void ()*, i8* } { i32 200, void ()* @_GLOBAL__I_000200, i8* null }, +// CHECK: { i32, void ()*, i8* } { i32 300, void ()* @_GLOBAL__I_000300, i8* null }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_init_priority_attr.cpp, i8* null }] // CHECK: _GLOBAL__I_000200() -// CHECK_NEXT: _Z3fooi(i32 3) +// CHECK: _Z3fooi(i32 3) +// CHECK-NEXT: ret void // CHECK: _GLOBAL__I_000300() -// CHECK_NEXT: _Z3fooi(i32 2) -// CHECK_NEXT: _Z3fooi(i32 1) - -// CHECK: _GLOBAL__I_a() -// CHECK_NEXT: _Z3fooi(i32 1) -// CHECK_NEXT: _Z3fooi(i32 4) +// CHECK: _Z3fooi(i32 2) +// CHECK-NEXT: _Z3fooi(i32 1) +// CHECK-NEXT: ret void + +// CHECK: _GLOBAL__sub_I_init_priority_attr.cpp() +// CHECK: _Z3fooi(i32 1) +// CHECK-NEXT: _Z3fooi(i32 4) +// CHECK-NEXT: ret void C c; A1 a1 __attribute__((init_priority (300))); diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp index 9f8e536a3b0c8..622cfa9536f3d 100644 --- a/test/CodeGenCXX/inline-functions.cpp +++ b/test/CodeGenCXX/inline-functions.cpp @@ -1,11 +1,12 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NORMAL +// RUN: %clang_cc1 %s -std=c++11 -fms-compatibility -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSVCCOMPAT // CHECK: ; ModuleID struct A { inline void f(); }; -// CHECK-NOT-LABEL: define void @_ZN1A1fEv +// CHECK-NOT: define void @_ZN1A1fEv void A::f() { } template<typename> struct B { }; @@ -67,3 +68,56 @@ namespace test2 { } // CHECK-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE } + +// MSVCCOMPAT-LABEL: define weak_odr void @_Z17ExternAndInlineFnv +// NORMAL-NOT: _Z17ExternAndInlineFnv +extern inline void ExternAndInlineFn() {} + +// MSVCCOMPAT-LABEL: define weak_odr void @_Z18InlineThenExternFnv +// NORMAL-NOT: _Z18InlineThenExternFnv +inline void InlineThenExternFn() {} +extern void InlineThenExternFn(); + +// CHECK-LABEL: define void @_Z18ExternThenInlineFnv +extern void ExternThenInlineFn() {} + +// MSVCCOMPAT-LABEL: define weak_odr void @_Z25ExternThenInlineThenDefFnv +// NORMAL-NOT: _Z25ExternThenInlineThenDefFnv +extern void ExternThenInlineThenDefFn(); +inline void ExternThenInlineThenDefFn(); +void ExternThenInlineThenDefFn() {} + +// MSVCCOMPAT-LABEL: define weak_odr void @_Z25InlineThenExternThenDefFnv +// NORMAL-NOT: _Z25InlineThenExternThenDefFnv +inline void InlineThenExternThenDefFn(); +extern void InlineThenExternThenDefFn(); +void InlineThenExternThenDefFn() {} + +// MSVCCOMPAT-LABEL: define weak_odr i32 @_Z20ExternAndConstexprFnv +// NORMAL-NOT: _Z17ExternAndConstexprFnv +extern constexpr int ExternAndConstexprFn() { return 0; } + +// CHECK-NOT: _Z11ConstexprFnv +constexpr int ConstexprFn() { return 0; } + +template <typename T> +extern inline void ExternInlineOnPrimaryTemplate(T); + +// CHECK-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_ +template <> +void ExternInlineOnPrimaryTemplate(int) {} + +template <typename T> +extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(T); + +// MSVCCOMPAT-LABEL: define weak_odr void @_Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_ +// NORMAL-NOT: _Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_ +template <> +extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(int) {} + +struct TypeWithInlineMethods { + // CHECK-NOT: _ZN21TypeWithInlineMethods9StaticFunEv + static void StaticFun() {} + // CHECK-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv + void NonStaticFun() { StaticFun(); } +}; diff --git a/test/CodeGenCXX/instrument-functions.cpp b/test/CodeGenCXX/instrument-functions.cpp index 253e096108930..587b6389c9a95 100644 --- a/test/CodeGenCXX/instrument-functions.cpp +++ b/test/CodeGenCXX/instrument-functions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions | FileCheck %s +// RUN: %clang_cc1 -S -emit-llvm -triple %itanium_abi_triple -o - %s -finstrument-functions | FileCheck %s // CHECK: @_Z5test1i int test1(int x) { diff --git a/test/CodeGenCXX/int64_uint64.cpp b/test/CodeGenCXX/int64_uint64.cpp new file mode 100644 index 0000000000000..aad6ea0b741de --- /dev/null +++ b/test/CodeGenCXX/int64_uint64.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple arm-linux-guneabi \ +// RUN: -target-cpu cortex-a8 \ +// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-ARM %s + +// RUN: %clang_cc1 -triple arm64-linux-gnueabi \ +// RUN: -target-feature +neon \ +// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-AARCH64 %s + +// Test if int64_t and uint64_t can be correctly mangled. + +#include "arm_neon.h" +// CHECK-ARM: f1x( +// CHECK-AARCH64: f1l( +void f1(int64_t a) {} +// CHECK-ARM: f2y( +// CHECK-AARCH64: f2m( +void f2(uint64_t a) {} +// CHECK-ARM: f3Px( +// CHECK-AARCH64: f3Pl( +void f3(int64_t *ptr) {} +// CHECK-ARM: f4Py( +// CHECK-AARCH64: f4Pm( +void f4(uint64_t *ptr) {} diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp index 56cb81030922c..77b16704dd173 100644 --- a/test/CodeGenCXX/internal-linkage.cpp +++ b/test/CodeGenCXX/internal-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s struct Global { Global(); }; template<typename T> struct X { X() {} }; diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp index 96b857225267e..ce7f2c674ba59 100644 --- a/test/CodeGenCXX/linetable-cleanup.cpp +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -46,12 +46,14 @@ void bar() void baz() { if (!foo()) - // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[SCOPE1:.*]] = metadata !{{{.*}}, i32 [[@LINE-1]], {{.*}}} ; [ DW_TAG_lexical_block ] + // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata ![[SCOPE1]], null} return; if (foo()) { // no cleanup - // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: {{.*}} = metadata !{i32 [[@LINE+2]], i32 0, metadata ![[SCOPE2:.*]], null} + // CHECK: ![[SCOPE2]] = metadata !{{{.*}}, i32 [[@LINE-3]], {{.*}}} ; [ DW_TAG_lexical_block ] return; } // CHECK: ![[RETBAZ]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp new file mode 100644 index 0000000000000..14a5067cf3ea7 --- /dev/null +++ b/test/CodeGenCXX/linetable-eh.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s + +// Test that emitting a landing pad does not affect the line table +// entries for the code that triggered it. + +// CHECK: call void @llvm.dbg.declare +// CHECK: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[CURRENT_ADDR:.*]]), !dbg ![[DBG1:.*]] +// CHECK: unwind label %{{.*}}, !dbg ![[DBG1]] +// CHECK: store i64 %{{.*}}, i64* %current_address, align 8, !dbg ![[DBG4:.*]] +// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[FOUND_IT:.*]]), !dbg ![[DBG2:.*]] +// CHECK: = landingpad +// CHECK-NEXT: cleanup, !dbg ![[DBG3:.*]] +// CHECK-DAG: ![[CURRENT_ADDR]] = {{.*}} [current_address] +// CHECK-DAG: ![[FOUND_IT]] = {{.*}} [found_it] +// CHECK-DAG: ![[DBG1]] = metadata !{i32 256, +// CHECK-DAG: ![[DBG2]] = metadata !{i32 257, +// CHECK-DAG: ![[DBG3]] = metadata !{i32 268, +// CHECK-DAG: ![[DBG4]] = metadata !{i32 256, +typedef unsigned long long uint64_t; +template<class _Tp> class shared_ptr { +public: + typedef _Tp element_type; + element_type* __ptr_; + ~shared_ptr(); + element_type* operator->() const noexcept {return __ptr_;} +}; +class Context { +public: + uint64_t GetIt(); +}; +class Foo +{ + bool bar(); + virtual shared_ptr<Context> GetContext () = 0; +}; +# 253 "Foo.cpp" 3 +bool +Foo::bar () +{ + uint64_t current_address = GetContext()->GetIt(); + bool found_it = false; +# 267 "Foo.cpp" 3 + return found_it; +} diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp new file mode 100644 index 0000000000000..ce46306fed0dc --- /dev/null +++ b/test/CodeGenCXX/linetable-fnbegin.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// Test that the line table info for Foo<T>::bar() is pointing to the +// right header file. +// CHECK: define{{.*}}bar +// CHECK-NOT: define +// CHECK: ret {{.*}}, !dbg [[DBG:.*]] +// CHECK: [[HPP:.*]] = metadata !{metadata !"./template.hpp", +// CHECK: [[SP:.*]] = metadata !{i32 786478, metadata [[HPP]],{{.*}}[ DW_TAG_subprogram ] [line 22] [def] [bar] +// We shouldn't need a lexical block for this function. +// CHECK: [[DBG]] = metadata !{i32 23, i32 0, metadata [[SP]], null} + + +# 1 "./template.h" 1 +template <typename T> +class Foo { +public: + int bar(); +}; +# 21 "./template.hpp" +template <typename T> +int Foo<T>::bar() { + return 23; +} +int main (int argc, const char * argv[]) +{ + Foo<int> f; + return f.bar(); +} diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp index 19f1b20773c00..60e53c6444e22 100644 --- a/test/CodeGenCXX/linkage.cpp +++ b/test/CodeGenCXX/linkage.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s namespace test1 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_( template <typename T> void f(T) {} inline void *g() { struct S { @@ -12,7 +12,7 @@ namespace test1 { } namespace test2 { - // CHECK-DAG-LABEL: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_( + // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_( template <typename T> void f(T) {} static inline void *g() { struct S { @@ -23,7 +23,7 @@ namespace test2 { } namespace test3 { - // CHECK-DAG-LABEL: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_( + // CHECK-DAG: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_( template <typename T> void f(T) {} void *g() { struct S { @@ -34,7 +34,7 @@ namespace test3 { } namespace test4 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_( template <typename T> void f(T) {} template <int N> inline void *g() { struct S { @@ -46,7 +46,7 @@ namespace test4 { } namespace test5 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_( template <typename T> void f(T) {} template <int N> inline void *g() { struct S { @@ -58,7 +58,7 @@ namespace test5 { } namespace test6 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv( + // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv( template <typename T> void f() {} inline void *g() { @@ -76,7 +76,7 @@ namespace test6 { } namespace test7 { - // CHECK-DAG-LABEL: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv( + // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv( template <typename T> void f() {} void *g() { @@ -94,7 +94,7 @@ namespace test7 { } namespace test8 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test81fIZNS_1gEvE1SEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test81fIZNS_1gEvE1SEEvT_( template <typename T> void f(T) {} inline void *g() { enum S { @@ -105,7 +105,7 @@ namespace test8 { } namespace test9 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_( template <typename T> void f(T) {} inline void *g() { struct S { @@ -116,7 +116,7 @@ namespace test9 { } namespace test10 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_( + // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_( template <typename T> void f(T) {} inline void *g() { struct S { @@ -128,7 +128,7 @@ namespace test10 { } namespace test11 { - // CHECK-DAG-LABEL: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_( + // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_( namespace { struct I { }; @@ -145,7 +145,7 @@ namespace test11 { } namespace test12 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test123fooIZNS_3barIZNS_3zedEvE2S2EEPvvE2S1EEvv + // CHECK-DAG: define linkonce_odr void @_ZN6test123fooIZNS_3barIZNS_3zedEvE2S2EEPvvE2S1EEvv template <typename T> void foo() {} template <typename T> inline void *bar() { enum S1 { @@ -161,7 +161,7 @@ namespace test12 { } namespace test13 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZZN6test133fooEvEN1S3barEv( + // CHECK-DAG: define linkonce_odr void @_ZZN6test133fooEvEN1S3barEv( inline void *foo() { struct S { static void bar() {} @@ -172,7 +172,7 @@ namespace test13 { } namespace test14 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv( template <typename T> struct foo { template <T *P> static void bar() {} static void *g() { return (void *)bar<nullptr>; } @@ -186,7 +186,7 @@ namespace test14 { } namespace test15 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv( template <class T> void zed() {} template <class T> void *foo() { class bar { @@ -197,7 +197,7 @@ namespace test15 { } namespace test16 { - // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv( + // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv( template <class T> void zed() {} template <class T> struct foo { static void *bar(); @@ -212,7 +212,7 @@ namespace test16 { namespace test17 { // CHECK-DAG: @_ZZN6test173fooILi42EEEPivE3bar = linkonce_odr - // CHECK-DAG-LABEL: define weak_odr i32* @_ZN6test173fooILi42EEEPiv( + // CHECK-DAG: define weak_odr i32* @_ZN6test173fooILi42EEEPiv( template<int I> int *foo() { static int bar; @@ -220,3 +220,11 @@ namespace test17 { } template int *foo<42>(); } + +// PR18408 +namespace test18 { + template<template<typename> class> struct A {}; + struct B { template<typename> struct C; }; + void f(A<B::C>) {} + // CHECK-DAG: define void @_ZN6test181fENS_1AINS_1B1CEEE( +} diff --git a/test/CodeGenCXX/mangle-abi-examples.cpp b/test/CodeGenCXX/mangle-abi-examples.cpp index 7124078320b04..6fb82cf8da5f7 100644 --- a/test/CodeGenCXX/mangle-abi-examples.cpp +++ b/test/CodeGenCXX/mangle-abi-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // CHECK: @_ZTVZ3foovEN1C1DE = // CHECK: @_ZTVZN1A3fooEiE1B = diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp index 4a4a1f3f56e9b..a0b3c1aff2245 100644 --- a/test/CodeGenCXX/mangle-address-space.cpp +++ b/test/CodeGenCXX/mangle-address-space.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s // CHECK-LABEL: define void @_Z2f0Pc void f0(char *p) { } diff --git a/test/CodeGenCXX/mangle-alias-template.cpp b/test/CodeGenCXX/mangle-alias-template.cpp index b6719c5452338..1dbb3eb67ad70 100644 --- a/test/CodeGenCXX/mangle-alias-template.cpp +++ b/test/CodeGenCXX/mangle-alias-template.cpp @@ -11,10 +11,6 @@ template<typename T> void g(T); template<template<typename> class F> void h(F<int>); -template<typename,typename,typename> struct S {}; -template<typename T, typename U> using U = S<T, int, U>; -template<typename...Ts> void h(U<Ts...>, Ts...); - // CHECK-LABEL: define void @_Z1zv( void z() { vector<int> VI; @@ -42,7 +38,4 @@ void z() { Vec<Vec<int>> VVI; g(VVI); // CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_( - - // CHECK: call void @_Z1hIJidEEv1UIDpT_ES2_ - h({}, 0, 0.0); } diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp index 659b437a0ef3d..e8d3f1983d258 100644 --- a/test/CodeGenCXX/mangle-lambdas.cpp +++ b/test/CodeGenCXX/mangle-lambdas.cpp @@ -192,7 +192,7 @@ namespace PR12123 { }; void B::h() { f(); } } -// CHECK-LABEL: define linkonce_odr %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv namespace PR12808 { template <typename> struct B { diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp index 8b950fcd17766..848e4604c4f20 100644 --- a/test/CodeGenCXX/mangle-local-class-names.cpp +++ b/test/CodeGenCXX/mangle-local-class-names.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // CHECK: @_ZZ4FUNCvEN4SSSSC1ERKf // CHECK: @_ZZ4FUNCvEN4SSSSC2E_0RKf diff --git a/test/CodeGenCXX/mangle-local-class-vtables.cpp b/test/CodeGenCXX/mangle-local-class-vtables.cpp index d9d3afe459337..078d735d8f053 100644 --- a/test/CodeGenCXX/mangle-local-class-vtables.cpp +++ b/test/CodeGenCXX/mangle-local-class-vtables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // CHECK: @_ZTVZN1J1KEvE1C = {{.*}} @_ZTIZN1J1KEvE1C {{.*}} @_ZZN1J1KEvENK1C1FEv // CHECK: @_ZTIZN1J1KEvE1C = {{.*}} @_ZTSZN1J1KEvE1C diff --git a/test/CodeGenCXX/mangle-local-classes-nested.cpp b/test/CodeGenCXX/mangle-local-classes-nested.cpp index fafa5d4e58e6d..cee541f8156a9 100644 --- a/test/CodeGenCXX/mangle-local-classes-nested.cpp +++ b/test/CodeGenCXX/mangle-local-classes-nested.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // CHECK: @_ZTVZZ1HvEN1S1IEvE1S = diff --git a/test/CodeGenCXX/mangle-ms-abi-examples.cpp b/test/CodeGenCXX/mangle-ms-abi-examples.cpp index d6726cab0d588..5dc9d2e71dab6 100644 --- a/test/CodeGenCXX/mangle-ms-abi-examples.cpp +++ b/test/CodeGenCXX/mangle-ms-abi-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s // CHECK: @"\01??_7D@C@?1??foo@@YAXXZ@6B@" = // CHECK: @"\01??_7B@?1??foo@A@@QAEXH@Z@6B@" = @@ -11,7 +11,7 @@ struct A { B(); } }; -void foo () { +inline void foo () { struct C { struct D { virtual ~D() {} }; void bar () { @@ -25,4 +25,6 @@ void foo () { C::D(); C().bar(); } - +void call () { + foo(); +} diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp index 50a238340e185..fae2e1ab2dfa4 100644 --- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp +++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s void foo(const unsigned int) {} // CHECK: "\01?foo@@YAXI@Z" @@ -37,6 +37,22 @@ void foo_sad(char * const volatile x) {} // CHECK: "\01?foo_sad@@YAXSAD@Z" // X64: "\01?foo_sad@@YAXSEAD@Z" +void foo_piad(char * __restrict x) {} +// CHECK: "\01?foo_piad@@YAXPIAD@Z" +// X64: "\01?foo_piad@@YAXPEIAD@Z" + +void foo_qiad(char * const __restrict x) {} +// CHECK: "\01?foo_qiad@@YAXQIAD@Z" +// X64: "\01?foo_qiad@@YAXQEIAD@Z" + +void foo_riad(char * volatile __restrict x) {} +// CHECK: "\01?foo_riad@@YAXRIAD@Z" +// X64: "\01?foo_riad@@YAXREIAD@Z" + +void foo_siad(char * const volatile __restrict x) {} +// CHECK: "\01?foo_siad@@YAXSIAD@Z" +// X64: "\01?foo_siad@@YAXSEIAD@Z" + void foo_papad(char ** x) {} // CHECK: "\01?foo_papad@@YAXPAPAD@Z" // X64: "\01?foo_papad@@YAXPEAPEAD@Z" @@ -238,3 +254,7 @@ void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {} void mangle_yes_backref3(ptr_to_fun_type *const, void (**const)(void)) {} // CHECK: "\01?mangle_yes_backref3@@YAXQAP6AXXZ0@Z" // X64: "\01?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z" + +void mangle_yes_backref4(int *const __restrict, int *const __restrict) {} +// CHECK: "\01?mangle_yes_backref4@@YAXQIAH0@Z" +// X64: "\01?mangle_yes_backref4@@YAXQEIAH0@Z" diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp index e10cc8e32986f..5d4b6722f5072 100644 --- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp +++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s template<class X, class Y, class Z> class A {}; diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp index 4f17326888331..25a058a30dbef 100644 --- a/test/CodeGenCXX/mangle-ms-back-references.cpp +++ b/test/CodeGenCXX/mangle-ms-back-references.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s void f1(const char* a, const char* b) {} // CHECK: "\01?f1@@YAXPBD0@Z" diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 6947a53c4d1e2..373d2b7b957f1 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s + +// CHECK: "\01?DeducedType@@3HA" +auto DeducedType = 30; // CHECK: "\01?LRef@@YAXAAH@Z" void LRef(int& a) { } @@ -9,3 +12,130 @@ int RRef(int&& a) { return a; } // CHECK: "\01?Null@@YAX$$T@Z" namespace std { typedef decltype(__nullptr) nullptr_t; } void Null(std::nullptr_t) {} + +namespace EnumMangling { + extern enum Enum01 { } Enum; + extern enum Enum02 : bool { } BoolEnum; + extern enum Enum03 : char { } CharEnum; + extern enum Enum04 : signed char { } SCharEnum; + extern enum Enum05 : unsigned char { } UCharEnum; + extern enum Enum06 : short { } SShortEnum; + extern enum Enum07 : unsigned short { } UShortEnum; + extern enum Enum08 : int { } SIntEnum; + extern enum Enum09 : unsigned int { } UIntEnum; + extern enum Enum10 : long { } SLongEnum; + extern enum Enum11 : unsigned long { } ULongEnum; + extern enum Enum12 : long long { } SLongLongEnum; + extern enum Enum13 : unsigned long long { } ULongLongEnum; +// CHECK-DAG: @"\01?Enum@EnumMangling@@3W4Enum01@1@A" +// CHECK-DAG: @"\01?BoolEnum@EnumMangling@@3W4Enum02@1@A +// CHECK-DAG: @"\01?CharEnum@EnumMangling@@3W4Enum03@1@A +// CHECK-DAG: @"\01?SCharEnum@EnumMangling@@3W4Enum04@1@A +// CHECK-DAG: @"\01?UCharEnum@EnumMangling@@3W4Enum05@1@A +// CHECK-DAG: @"\01?SShortEnum@EnumMangling@@3W4Enum06@1@A" +// CHECK-DAG: @"\01?UShortEnum@EnumMangling@@3W4Enum07@1@A" +// CHECK-DAG: @"\01?SIntEnum@EnumMangling@@3W4Enum08@1@A" +// CHECK-DAG: @"\01?UIntEnum@EnumMangling@@3W4Enum09@1@A" +// CHECK-DAG: @"\01?SLongEnum@EnumMangling@@3W4Enum10@1@A" +// CHECK-DAG: @"\01?ULongEnum@EnumMangling@@3W4Enum11@1@A" +// CHECK-DAG: @"\01?SLongLongEnum@EnumMangling@@3W4Enum12@1@A" +// CHECK-DAG: @"\01?ULongLongEnum@EnumMangling@@3W4Enum13@1@A" + decltype(Enum) *UseEnum() { return &Enum; } + decltype(BoolEnum) *UseBoolEnum() { return &BoolEnum; } + decltype(CharEnum) *UseCharEnum() { return &CharEnum; } + decltype(SCharEnum) *UseSCharEnum() { return &SCharEnum; } + decltype(UCharEnum) *UseUCharEnum() { return &UCharEnum; } + decltype(SShortEnum) *UseSShortEnum() { return &SShortEnum; } + decltype(UShortEnum) *UseUShortEnum() { return &UShortEnum; } + decltype(SIntEnum) *UseSIntEnum() { return &SIntEnum; } + decltype(UIntEnum) *UseUIntEnum() { return &UIntEnum; } + decltype(SLongEnum) *UseSLongEnum() { return &SLongEnum; } + decltype(ULongEnum) *UseULongEnum() { return &ULongEnum; } + decltype(SLongLongEnum) *UseSLongLongEnum() { return &SLongLongEnum; } + decltype(ULongLongEnum) *UseULongLongEnum() { return &ULongLongEnum; } + extern enum class EnumClass01 { } EnumClass; + extern enum class EnumClass02 : bool { } BoolEnumClass; + extern enum class EnumClass03 : char { } CharEnumClass; + extern enum class EnumClass04 : signed char { } SCharEnumClass; + extern enum class EnumClass05 : unsigned char { } UCharEnumClass; + extern enum class EnumClass06 : short { } SShortEnumClass; + extern enum class EnumClass07 : unsigned short { } UShortEnumClass; + extern enum class EnumClass08 : int { } SIntEnumClass; + extern enum class EnumClass09 : unsigned int { } UIntEnumClass; + extern enum class EnumClass10 : long { } SLongEnumClass; + extern enum class EnumClass11 : unsigned long { } ULongEnumClass; + extern enum class EnumClass12 : long long { } SLongLongEnumClass; + extern enum class EnumClass13 : unsigned long long { } ULongLongEnumClass; +// CHECK-DAG: @"\01?EnumClass@EnumMangling@@3W4EnumClass01@1@A" +// CHECK-DAG: @"\01?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A +// CHECK-DAG: @"\01?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A +// CHECK-DAG: @"\01?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A +// CHECK-DAG: @"\01?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A +// CHECK-DAG: @"\01?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A" +// CHECK-DAG: @"\01?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A" +// CHECK-DAG: @"\01?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A" +// CHECK-DAG: @"\01?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A" +// CHECK-DAG: @"\01?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A" +// CHECK-DAG: @"\01?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A" +// CHECK-DAG: @"\01?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A" +// CHECK-DAG: @"\01?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A" + decltype(EnumClass) *UseEnumClass() { return &EnumClass; } + decltype(BoolEnumClass) *UseBoolEnumClass() { return &BoolEnumClass; } + decltype(CharEnumClass) *UseCharEnumClass() { return &CharEnumClass; } + decltype(SCharEnumClass) *UseSCharEnumClass() { return &SCharEnumClass; } + decltype(UCharEnumClass) *UseUCharEnumClass() { return &UCharEnumClass; } + decltype(SShortEnumClass) *UseSShortEnumClass() { return &SShortEnumClass; } + decltype(UShortEnumClass) *UseUShortEnumClass() { return &UShortEnumClass; } + decltype(SIntEnumClass) *UseSIntEnumClass() { return &SIntEnumClass; } + decltype(UIntEnumClass) *UseUIntEnumClass() { return &UIntEnumClass; } + decltype(SLongEnumClass) *UseSLongEnumClass() { return &SLongEnumClass; } + decltype(ULongEnumClass) *UseULongEnumClass() { return &ULongEnumClass; } + decltype(SLongLongEnumClass) *UseSLongLongEnumClass() { return &SLongLongEnumClass; } + decltype(ULongLongEnumClass) *UseULongLongEnumClass() { return &ULongLongEnumClass; } +} + +namespace PR18022 { + +struct { } a; +decltype(a) fun(decltype(a) x, decltype(a)) { return x; } +// CHECK-DAG: ?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z + +} + +inline int define_lambda() { + static auto lambda = [] { static int local; ++local; return local; }; +// First, we have the static local variable of type "<lambda_1>" inside of +// "define_lambda". +// CHECK-DAG: ?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@@A +// Next, we have the "operator()" for "<lambda_1>" which is inside of +// "define_lambda". +// CHECK-DAG: ??R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ +// Finally, we have the local which is inside of "<lambda_1>" which is inside of +// "define_lambda". Hooray. +// CHECK-DAG: ?local@?2???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA + return lambda(); +} + +int call_lambda() { + return define_lambda(); +} + +namespace PR19361 { +struct A { + void foo() __restrict &; + void foo() __restrict &&; +}; +void A::foo() __restrict & {} +// CHECK-DAG: @"\01?foo@A@PR19361@@QIGAEXXZ" +void A::foo() __restrict && {} +// CHECK-DAG: @"\01?foo@A@PR19361@@QIHAEXXZ" +} + +int operator"" _deg(long double) { return 0; } +// CHECK-DAG: @"\01??__K_deg@@YAHO@Z" + +template <char...> +void templ_fun_with_pack() {} + +template void templ_fun_with_pack<>(); +// CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ" diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp new file mode 100644 index 0000000000000..03995611d2526 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s + +template <typename> int x = 0; + +// CHECK: "\01??$x@X@@3HA" +template <> int x<void>; +// CHECK: "\01??$x@H@@3HA" +template <> int x<int>; + +// CHECK: "\01?FunctionWithLocalType@@YA?A?<auto>@@XZ" +auto FunctionWithLocalType() { + struct LocalType {}; + return LocalType{}; +} + +// CHECK: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?0??FunctionWithLocalType@@YA?A?<auto>@@XZ@A" +auto ValueFromFunctionWithLocalType = FunctionWithLocalType(); + +// CHECK: "\01??R<lambda_0>@@QBE?A?<auto>@@XZ" +auto LambdaWithLocalType = [] { + struct LocalType {}; + return LocalType{}; +}; + +// CHECK: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?0???R<lambda_0>@@QBE?A?<auto>@@XZ@A" +auto ValueFromLambdaWithLocalType = LambdaWithLocalType(); + +template <typename T> +auto TemplateFuncionWithLocalLambda(T) { + auto LocalLambdaWithLocalType = []() { + struct LocalType {}; + return LocalType{}; + }; + return LocalLambdaWithLocalType(); +} + +// CHECK: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBA?A?3@XZ@A" +// CHECK: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z" +// CHECK: "\01??R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBA?A?1@XZ" +auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0); diff --git a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp index 87e04c645eced..37bbf099fab0a 100644 --- a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp +++ b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s void a1() {} // CHECK: "\01?a1@@YAXXZ" @@ -164,6 +164,12 @@ int S::* f8() { return 0; } int S::* const f9() { return 0; } // CHECK: "\01?f9@@YAQQS@@HXZ" +int S::* __restrict f10() { return 0; } +// CHECK: "\01?f10@@YAPIQS@@HXZ" + +int S::* const __restrict f11() { return 0; } +// CHECK: "\01?f11@@YAQIQS@@HXZ" + typedef int (*function_pointer)(int); function_pointer g1() { return 0; } diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp new file mode 100644 index 0000000000000..a77a04f71e0a1 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp @@ -0,0 +1,721 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s + +const char *l255 = "\xff"; +const char *l254 = "\xfe"; +const char *l253 = "\xfd"; +const char *l252 = "\xfc"; +const char *l251 = "\xfb"; +const char *l250 = "\xfa"; +const char *l249 = "\xf9"; +const char *l248 = "\xf8"; +const char *l247 = "\xf7"; +const char *l246 = "\xf6"; +const char *l245 = "\xf5"; +const char *l244 = "\xf4"; +const char *l243 = "\xf3"; +const char *l242 = "\xf2"; +const char *l241 = "\xf1"; +const char *l240 = "\xf0"; +const char *l239 = "\xef"; +const char *l238 = "\xee"; +const char *l237 = "\xed"; +const char *l236 = "\xec"; +const char *l235 = "\xeb"; +const char *l234 = "\xea"; +const char *l233 = "\xe9"; +const char *l232 = "\xe8"; +const char *l231 = "\xe7"; +const char *l230 = "\xe6"; +const char *l229 = "\xe5"; +const char *l228 = "\xe4"; +const char *l227 = "\xe3"; +const char *l226 = "\xe2"; +const char *l225 = "\xe1"; +const char *l224 = "\xe0"; +const char *l223 = "\xdf"; +const char *l222 = "\xde"; +const char *l221 = "\xdd"; +const char *l220 = "\xdc"; +const char *l219 = "\xdb"; +const char *l218 = "\xda"; +const char *l217 = "\xd9"; +const char *l216 = "\xd8"; +const char *l215 = "\xd7"; +const char *l214 = "\xd6"; +const char *l213 = "\xd5"; +const char *l212 = "\xd4"; +const char *l211 = "\xd3"; +const char *l210 = "\xd2"; +const char *l209 = "\xd1"; +const char *l208 = "\xd0"; +const char *l207 = "\xcf"; +const char *l206 = "\xce"; +const char *l205 = "\xcd"; +const char *l204 = "\xcc"; +const char *l203 = "\xcb"; +const char *l202 = "\xca"; +const char *l201 = "\xc9"; +const char *l200 = "\xc8"; +const char *l199 = "\xc7"; +const char *l198 = "\xc6"; +const char *l197 = "\xc5"; +const char *l196 = "\xc4"; +const char *l195 = "\xc3"; +const char *l194 = "\xc2"; +const char *l193 = "\xc1"; +const char *l192 = "\xc0"; +const char *l191 = "\xbf"; +const char *l190 = "\xbe"; +const char *l189 = "\xbd"; +const char *l188 = "\xbc"; +const char *l187 = "\xbb"; +const char *l186 = "\xba"; +const char *l185 = "\xb9"; +const char *l184 = "\xb8"; +const char *l183 = "\xb7"; +const char *l182 = "\xb6"; +const char *l181 = "\xb5"; +const char *l180 = "\xb4"; +const char *l179 = "\xb3"; +const char *l178 = "\xb2"; +const char *l177 = "\xb1"; +const char *l176 = "\xb0"; +const char *l175 = "\xaf"; +const char *l174 = "\xae"; +const char *l173 = "\xad"; +const char *l172 = "\xac"; +const char *l171 = "\xab"; +const char *l170 = "\xaa"; +const char *l169 = "\xa9"; +const char *l168 = "\xa8"; +const char *l167 = "\xa7"; +const char *l166 = "\xa6"; +const char *l165 = "\xa5"; +const char *l164 = "\xa4"; +const char *l163 = "\xa3"; +const char *l162 = "\xa2"; +const char *l161 = "\xa1"; +const char *l160 = "\xa0"; +const char *l159 = "\x9f"; +const char *l158 = "\x9e"; +const char *l157 = "\x9d"; +const char *l156 = "\x9c"; +const char *l155 = "\x9b"; +const char *l154 = "\x9a"; +const char *l153 = "\x99"; +const char *l152 = "\x98"; +const char *l151 = "\x97"; +const char *l150 = "\x96"; +const char *l149 = "\x95"; +const char *l148 = "\x94"; +const char *l147 = "\x93"; +const char *l146 = "\x92"; +const char *l145 = "\x91"; +const char *l144 = "\x90"; +const char *l143 = "\x8f"; +const char *l142 = "\x8e"; +const char *l141 = "\x8d"; +const char *l140 = "\x8c"; +const char *l139 = "\x8b"; +const char *l138 = "\x8a"; +const char *l137 = "\x89"; +const char *l136 = "\x88"; +const char *l135 = "\x87"; +const char *l134 = "\x86"; +const char *l133 = "\x85"; +const char *l132 = "\x84"; +const char *l131 = "\x83"; +const char *l130 = "\x82"; +const char *l129 = "\x81"; +const char *l128 = "\x80"; +const char *l127 = "\x7f"; +const char *l126 = "\x7e"; +const char *l125 = "\x7d"; +const char *l124 = "\x7c"; +const char *l123 = "\x7b"; +const char *l122 = "\x7a"; +const char *l121 = "\x79"; +const char *l120 = "\x78"; +const char *l119 = "\x77"; +const char *l118 = "\x76"; +const char *l117 = "\x75"; +const char *l116 = "\x74"; +const char *l115 = "\x73"; +const char *l114 = "\x72"; +const char *l113 = "\x71"; +const char *l112 = "\x70"; +const char *l111 = "\x6f"; +const char *l110 = "\x6e"; +const char *l109 = "\x6d"; +const char *l108 = "\x6c"; +const char *l107 = "\x6b"; +const char *l106 = "\x6a"; +const char *l105 = "\x69"; +const char *l104 = "\x68"; +const char *l103 = "\x67"; +const char *l102 = "\x66"; +const char *l101 = "\x65"; +const char *l100 = "\x64"; +const char *l99 = "\x63"; +const char *l98 = "\x62"; +const char *l97 = "\x61"; +const char *l96 = "\x60"; +const char *l95 = "\x5f"; +const char *l94 = "\x5e"; +const char *l93 = "\x5d"; +const char *l92 = "\x5c"; +const char *l91 = "\x5b"; +const char *l90 = "\x5a"; +const char *l89 = "\x59"; +const char *l88 = "\x58"; +const char *l87 = "\x57"; +const char *l86 = "\x56"; +const char *l85 = "\x55"; +const char *l84 = "\x54"; +const char *l83 = "\x53"; +const char *l82 = "\x52"; +const char *l81 = "\x51"; +const char *l80 = "\x50"; +const char *l79 = "\x4f"; +const char *l78 = "\x4e"; +const char *l77 = "\x4d"; +const char *l76 = "\x4c"; +const char *l75 = "\x4b"; +const char *l74 = "\x4a"; +const char *l73 = "\x49"; +const char *l72 = "\x48"; +const char *l71 = "\x47"; +const char *l70 = "\x46"; +const char *l69 = "\x45"; +const char *l68 = "\x44"; +const char *l67 = "\x43"; +const char *l66 = "\x42"; +const char *l65 = "\x41"; +const char *l64 = "\x40"; +const char *l63 = "\x3f"; +const char *l62 = "\x3e"; +const char *l61 = "\x3d"; +const char *l60 = "\x3c"; +const char *l59 = "\x3b"; +const char *l58 = "\x3a"; +const char *l57 = "\x39"; +const char *l56 = "\x38"; +const char *l55 = "\x37"; +const char *l54 = "\x36"; +const char *l53 = "\x35"; +const char *l52 = "\x34"; +const char *l51 = "\x33"; +const char *l50 = "\x32"; +const char *l49 = "\x31"; +const char *l48 = "\x30"; +const char *l47 = "\x2f"; +const char *l46 = "\x2e"; +const char *l45 = "\x2d"; +const char *l44 = "\x2c"; +const char *l43 = "\x2b"; +const char *l42 = "\x2a"; +const char *l41 = "\x29"; +const char *l40 = "\x28"; +const char *l39 = "\x27"; +const char *l38 = "\x26"; +const char *l37 = "\x25"; +const char *l36 = "\x24"; +const char *l35 = "\x23"; +const char *l34 = "\x22"; +const char *l33 = "\x21"; +const char *l32 = "\x20"; +const char *l31 = "\x1f"; +const char *l30 = "\x1e"; +const char *l29 = "\x1d"; +const char *l28 = "\x1c"; +const char *l27 = "\x1b"; +const char *l26 = "\x1a"; +const char *l25 = "\x19"; +const char *l24 = "\x18"; +const char *l23 = "\x17"; +const char *l22 = "\x16"; +const char *l21 = "\x15"; +const char *l20 = "\x14"; +const char *l19 = "\x13"; +const char *l18 = "\x12"; +const char *l17 = "\x11"; +const char *l16 = "\x10"; +const char *l15 = "\xf"; +const char *l14 = "\xe"; +const char *l13 = "\xd"; +const char *l12 = "\xc"; +const char *l11 = "\xb"; +const char *l10 = "\xa"; +const char *l9 = "\x9"; +const char *l8 = "\x8"; +const char *l7 = "\x7"; +const char *l6 = "\x6"; +const char *l5 = "\x5"; +const char *l4 = "\x4"; +const char *l3 = "\x3"; +const char *l2 = "\x2"; +const char *l1 = "\x1"; +const char *l0 = "\x0"; + +// CHECK: @"\01??_C@_01CNACBAHC@?$PP?$AA@" +// CHECK: @"\01??_C@_01DEBJCBDD@?$PO?$AA@" +// CHECK: @"\01??_C@_01BPDEHCPA@?$PN?$AA@" +// CHECK: @"\01??_C@_01GCPEDLB@?$PM?$AA@" +// CHECK: @"\01??_C@_01EJGONFHG@?$PL?$AA@" +// CHECK: @"\01??_C@_01FAHFOEDH@?z?$AA@" +// CHECK: @"\01??_C@_01HLFILHPE@?y?$AA@" +// CHECK: @"\01??_C@_01GCEDIGLF@?x?$AA@" +// CHECK: @"\01??_C@_01OFNLJKHK@?w?$AA@" +// CHECK: @"\01??_C@_01PMMAKLDL@?v?$AA@" +// CHECK: @"\01??_C@_01NHONPIPI@?u?$AA@" +// CHECK: @"\01??_C@_01MOPGMJLJ@?t?$AA@" +// CHECK: @"\01??_C@_01IBLHFPHO@?s?$AA@" +// CHECK: @"\01??_C@_01JIKMGODP@?r?$AA@" +// CHECK: @"\01??_C@_01LDIBDNPM@?q?$AA@" +// CHECK: @"\01??_C@_01KKJKAMLN@?p?$AA@" +// CHECK: @"\01??_C@_01GHMAACCD@?o?$AA@" +// CHECK: @"\01??_C@_01HONLDDGC@?n?$AA@" +// CHECK: @"\01??_C@_01FFPGGAKB@?m?$AA@" +// CHECK: @"\01??_C@_01EMONFBOA@?l?$AA@" +// CHECK: @"\01??_C@_01DKMMHCH@?k?$AA@" +// CHECK: @"\01??_C@_01BKLHPGGG@?j?$AA@" +// CHECK: @"\01??_C@_01DBJKKFKF@?i?$AA@" +// CHECK: @"\01??_C@_01CIIBJEOE@?h?$AA@" +// CHECK: @"\01??_C@_01KPBJIICL@?g?$AA@" +// CHECK: @"\01??_C@_01LGACLJGK@?f?$AA@" +// CHECK: @"\01??_C@_01JNCPOKKJ@?e?$AA@" +// CHECK: @"\01??_C@_01IEDENLOI@?d?$AA@" +// CHECK: @"\01??_C@_01MLHFENCP@?c?$AA@" +// CHECK: @"\01??_C@_01NCGOHMGO@?b?$AA@" +// CHECK: @"\01??_C@_01PJEDCPKN@?a?$AA@" +// CHECK: @"\01??_C@_01OAFIBOOM@?$OA?$AA@" +// CHECK: @"\01??_C@_01LIIGDENA@?$NP?$AA@" +// CHECK: @"\01??_C@_01KBJNAFJB@?$NO?$AA@" +// CHECK: @"\01??_C@_01IKLAFGFC@?$NN?$AA@" +// CHECK: @"\01??_C@_01JDKLGHBD@?$NM?$AA@" +// CHECK: @"\01??_C@_01NMOKPBNE@?$NL?$AA@" +// CHECK: @"\01??_C@_01MFPBMAJF@?Z?$AA@" +// CHECK: @"\01??_C@_01OONMJDFG@?Y?$AA@" +// CHECK: @"\01??_C@_01PHMHKCBH@?X?$AA@" +// CHECK: @"\01??_C@_01HAFPLONI@?W?$AA@" +// CHECK: @"\01??_C@_01GJEEIPJJ@?V?$AA@" +// CHECK: @"\01??_C@_01ECGJNMFK@?U?$AA@" +// CHECK: @"\01??_C@_01FLHCONBL@?T?$AA@" +// CHECK: @"\01??_C@_01BEDDHLNM@?S?$AA@" +// CHECK: @"\01??_C@_01NCIEKJN@?R?$AA@" +// CHECK: @"\01??_C@_01CGAFBJFO@?Q?$AA@" +// CHECK: @"\01??_C@_01DPBOCIBP@?P?$AA@" +// CHECK: @"\01??_C@_01PCEECGIB@?O?$AA@" +// CHECK: @"\01??_C@_01OLFPBHMA@?N?$AA@" +// CHECK: @"\01??_C@_01MAHCEEAD@?M?$AA@" +// CHECK: @"\01??_C@_01NJGJHFEC@?L?$AA@" +// CHECK: @"\01??_C@_01JGCIODIF@?K?$AA@" +// CHECK: @"\01??_C@_01IPDDNCME@?J?$AA@" +// CHECK: @"\01??_C@_01KEBOIBAH@?I?$AA@" +// CHECK: @"\01??_C@_01LNAFLAEG@?H?$AA@" +// CHECK: @"\01??_C@_01DKJNKMIJ@?G?$AA@" +// CHECK: @"\01??_C@_01CDIGJNMI@?F?$AA@" +// CHECK: @"\01??_C@_01IKLMOAL@?E?$AA@" +// CHECK: @"\01??_C@_01BBLAPPEK@?D?$AA@" +// CHECK: @"\01??_C@_01FOPBGJIN@?C?$AA@" +// CHECK: @"\01??_C@_01EHOKFIMM@?B?$AA@" +// CHECK: @"\01??_C@_01GMMHALAP@?A?$AA@" +// CHECK: @"\01??_C@_01HFNMDKEO@?$MA?$AA@" +// CHECK: @"\01??_C@_01NNHLFPHH@?$LP?$AA@" +// CHECK: @"\01??_C@_01MEGAGODG@?$LO?$AA@" +// CHECK: @"\01??_C@_01OPENDNPF@?$LN?$AA@" +// CHECK: @"\01??_C@_01PGFGAMLE@?$LM?$AA@" +// CHECK: @"\01??_C@_01LJBHJKHD@?$LL?$AA@" +// CHECK: @"\01??_C@_01KAAMKLDC@?$LK?$AA@" +// CHECK: @"\01??_C@_01ILCBPIPB@?$LJ?$AA@" +// CHECK: @"\01??_C@_01JCDKMJLA@?$LI?$AA@" +// CHECK: @"\01??_C@_01BFKCNFHP@?$LH?$AA@" +// CHECK: @"\01??_C@_01MLJOEDO@?$LG?$AA@" +// CHECK: @"\01??_C@_01CHJELHPN@?$LF?$AA@" +// CHECK: @"\01??_C@_01DOIPIGLM@?$LE?$AA@" +// CHECK: @"\01??_C@_01HBMOBAHL@?$LD?$AA@" +// CHECK: @"\01??_C@_01GINFCBDK@?$LC?$AA@" +// CHECK: @"\01??_C@_01EDPIHCPJ@?$LB?$AA@" +// CHECK: @"\01??_C@_01FKODEDLI@?$LA?$AA@" +// CHECK: @"\01??_C@_01JHLJENCG@?$KP?$AA@" +// CHECK: @"\01??_C@_01IOKCHMGH@?$KO?$AA@" +// CHECK: @"\01??_C@_01KFIPCPKE@?$KN?$AA@" +// CHECK: @"\01??_C@_01LMJEBOOF@?$KM?$AA@" +// CHECK: @"\01??_C@_01PDNFIICC@?$KL?$AA@" +// CHECK: @"\01??_C@_01OKMOLJGD@?$KK?$AA@" +// CHECK: @"\01??_C@_01MBODOKKA@?$KJ?$AA@" +// CHECK: @"\01??_C@_01NIPINLOB@?$KI?$AA@" +// CHECK: @"\01??_C@_01FPGAMHCO@?$KH?$AA@" +// CHECK: @"\01??_C@_01EGHLPGGP@?$KG?$AA@" +// CHECK: @"\01??_C@_01GNFGKFKM@?$KF?$AA@" +// CHECK: @"\01??_C@_01HEENJEON@?$KE?$AA@" +// CHECK: @"\01??_C@_01DLAMACCK@?$KD?$AA@" +// CHECK: @"\01??_C@_01CCBHDDGL@?$KC?$AA@" +// CHECK: @"\01??_C@_01JDKGAKI@?$KB?$AA@" +// CHECK: @"\01??_C@_01BACBFBOJ@?$KA?$AA@" +// CHECK: @"\01??_C@_01EIPPHLNF@?$JP?$AA@" +// CHECK: @"\01??_C@_01FBOEEKJE@?$JO?$AA@" +// CHECK: @"\01??_C@_01HKMJBJFH@?$JN?$AA@" +// CHECK: @"\01??_C@_01GDNCCIBG@?$JM?$AA@" +// CHECK: @"\01??_C@_01CMJDLONB@?$JL?$AA@" +// CHECK: @"\01??_C@_01DFIIIPJA@?$JK?$AA@" +// CHECK: @"\01??_C@_01BOKFNMFD@?$JJ?$AA@" +// CHECK: @"\01??_C@_01HLOONBC@?$JI?$AA@" +// CHECK: @"\01??_C@_01IACGPBNN@?$JH?$AA@" +// CHECK: @"\01??_C@_01JJDNMAJM@?$JG?$AA@" +// CHECK: @"\01??_C@_01LCBAJDFP@?$JF?$AA@" +// CHECK: @"\01??_C@_01KLALKCBO@?$JE?$AA@" +// CHECK: @"\01??_C@_01OEEKDENJ@?$JD?$AA@" +// CHECK: @"\01??_C@_01PNFBAFJI@?$JC?$AA@" +// CHECK: @"\01??_C@_01NGHMFGFL@?$JB?$AA@" +// CHECK: @"\01??_C@_01MPGHGHBK@?$JA?$AA@" +// CHECK: @"\01??_C@_01CDNGJIE@?$IP?$AA@" +// CHECK: @"\01??_C@_01BLCGFIMF@?$IO?$AA@" +// CHECK: @"\01??_C@_01DAALALAG@?$IN?$AA@" +// CHECK: @"\01??_C@_01CJBADKEH@?$IM?$AA@" +// CHECK: @"\01??_C@_01GGFBKMIA@?$IL?$AA@" +// CHECK: @"\01??_C@_01HPEKJNMB@?$IK?$AA@" +// CHECK: @"\01??_C@_01FEGHMOAC@?$IJ?$AA@" +// CHECK: @"\01??_C@_01ENHMPPED@?$II?$AA@" +// CHECK: @"\01??_C@_01MKOEODIM@?$IH?$AA@" +// CHECK: @"\01??_C@_01NDPPNCMN@?$IG?$AA@" +// CHECK: @"\01??_C@_01PINCIBAO@?$IF?$AA@" +// CHECK: @"\01??_C@_01OBMJLAEP@?$IE?$AA@" +// CHECK: @"\01??_C@_01KOIICGII@?$ID?$AA@" +// CHECK: @"\01??_C@_01LHJDBHMJ@?$IC?$AA@" +// CHECK: @"\01??_C@_01JMLOEEAK@?$IB?$AA@" +// CHECK: @"\01??_C@_01IFKFHFEL@?$IA?$AA@" +// CHECK: @"\01??_C@_01BGIBIIDJ@?$HP?$AA@" +// CHECK: @"\01??_C@_01PJKLJHI@?$HO?$AA@" +// CHECK: @"\01??_C@_01CELHOKLL@?$HN?$AA@" +// CHECK: @"\01??_C@_01DNKMNLPK@?$HM?$AA@" +// CHECK: @"\01??_C@_01HCONENDN@?$HL?$AA@" +// CHECK: @"\01??_C@_01GLPGHMHM@z?$AA@" +// CHECK: @"\01??_C@_01EANLCPLP@y?$AA@" +// CHECK: @"\01??_C@_01FJMABOPO@x?$AA@" +// CHECK: @"\01??_C@_01NOFIACDB@w?$AA@" +// CHECK: @"\01??_C@_01MHEDDDHA@v?$AA@" +// CHECK: @"\01??_C@_01OMGOGALD@u?$AA@" +// CHECK: @"\01??_C@_01PFHFFBPC@t?$AA@" +// CHECK: @"\01??_C@_01LKDEMHDF@s?$AA@" +// CHECK: @"\01??_C@_01KDCPPGHE@r?$AA@" +// CHECK: @"\01??_C@_01IIACKFLH@q?$AA@" +// CHECK: @"\01??_C@_01JBBJJEPG@p?$AA@" +// CHECK: @"\01??_C@_01FMEDJKGI@o?$AA@" +// CHECK: @"\01??_C@_01EFFIKLCJ@n?$AA@" +// CHECK: @"\01??_C@_01GOHFPIOK@m?$AA@" +// CHECK: @"\01??_C@_01HHGOMJKL@l?$AA@" +// CHECK: @"\01??_C@_01DICPFPGM@k?$AA@" +// CHECK: @"\01??_C@_01CBDEGOCN@j?$AA@" +// CHECK: @"\01??_C@_01KBJDNOO@i?$AA@" +// CHECK: @"\01??_C@_01BDACAMKP@h?$AA@" +// CHECK: @"\01??_C@_01JEJKBAGA@g?$AA@" +// CHECK: @"\01??_C@_01INIBCBCB@f?$AA@" +// CHECK: @"\01??_C@_01KGKMHCOC@e?$AA@" +// CHECK: @"\01??_C@_01LPLHEDKD@d?$AA@" +// CHECK: @"\01??_C@_01PAPGNFGE@c?$AA@" +// CHECK: @"\01??_C@_01OJONOECF@b?$AA@" +// CHECK: @"\01??_C@_01MCMALHOG@a?$AA@" +// CHECK: @"\01??_C@_01NLNLIGKH@?$GA?$AA@" +// CHECK: @"\01??_C@_01IDAFKMJL@_?$AA@" +// CHECK: @"\01??_C@_01JKBOJNNK@?$FO?$AA@" +// CHECK: @"\01??_C@_01LBDDMOBJ@?$FN?$AA@" +// CHECK: @"\01??_C@_01KICIPPFI@?2?$AA@" +// CHECK: @"\01??_C@_01OHGJGJJP@?$FL?$AA@" +// CHECK: @"\01??_C@_01POHCFINO@Z?$AA@" +// CHECK: @"\01??_C@_01NFFPALBN@Y?$AA@" +// CHECK: @"\01??_C@_01MMEEDKFM@X?$AA@" +// CHECK: @"\01??_C@_01ELNMCGJD@W?$AA@" +// CHECK: @"\01??_C@_01FCMHBHNC@V?$AA@" +// CHECK: @"\01??_C@_01HJOKEEBB@U?$AA@" +// CHECK: @"\01??_C@_01GAPBHFFA@T?$AA@" +// CHECK: @"\01??_C@_01CPLAODJH@S?$AA@" +// CHECK: @"\01??_C@_01DGKLNCNG@R?$AA@" +// CHECK: @"\01??_C@_01BNIGIBBF@Q?$AA@" +// CHECK: @"\01??_C@_01EJNLAFE@P?$AA@" +// CHECK: @"\01??_C@_01MJMHLOMK@O?$AA@" +// CHECK: @"\01??_C@_01NANMIPIL@N?$AA@" +// CHECK: @"\01??_C@_01PLPBNMEI@M?$AA@" +// CHECK: @"\01??_C@_01OCOKONAJ@L?$AA@" +// CHECK: @"\01??_C@_01KNKLHLMO@K?$AA@" +// CHECK: @"\01??_C@_01LELAEKIP@J?$AA@" +// CHECK: @"\01??_C@_01JPJNBJEM@I?$AA@" +// CHECK: @"\01??_C@_01IGIGCIAN@H?$AA@" +// CHECK: @"\01??_C@_01BBODEMC@G?$AA@" +// CHECK: @"\01??_C@_01BIAFAFID@F?$AA@" +// CHECK: @"\01??_C@_01DDCIFGEA@E?$AA@" +// CHECK: @"\01??_C@_01CKDDGHAB@D?$AA@" +// CHECK: @"\01??_C@_01GFHCPBMG@C?$AA@" +// CHECK: @"\01??_C@_01HMGJMAIH@B?$AA@" +// CHECK: @"\01??_C@_01FHEEJDEE@A?$AA@" +// CHECK: @"\01??_C@_01EOFPKCAF@?$EA?$AA@" +// CHECK: @"\01??_C@_01OGPIMHDM@?$DP?$AA@" +// CHECK: @"\01??_C@_01PPODPGHN@?$DO?$AA@" +// CHECK: @"\01??_C@_01NEMOKFLO@?$DN?$AA@" +// CHECK: @"\01??_C@_01MNNFJEPP@?$DM?$AA@" +// CHECK: @"\01??_C@_01ICJEACDI@?$DL?$AA@" +// CHECK: @"\01??_C@_01JLIPDDHJ@?3?$AA@" +// CHECK: @"\01??_C@_01LAKCGALK@9?$AA@" +// CHECK: @"\01??_C@_01KJLJFBPL@8?$AA@" +// CHECK: @"\01??_C@_01COCBENDE@7?$AA@" +// CHECK: @"\01??_C@_01DHDKHMHF@6?$AA@" +// CHECK: @"\01??_C@_01BMBHCPLG@5?$AA@" +// CHECK: @"\01??_C@_01FAMBOPH@4?$AA@" +// CHECK: @"\01??_C@_01EKENIIDA@3?$AA@" +// CHECK: @"\01??_C@_01FDFGLJHB@2?$AA@" +// CHECK: @"\01??_C@_01HIHLOKLC@1?$AA@" +// CHECK: @"\01??_C@_01GBGANLPD@0?$AA@" +// CHECK: @"\01??_C@_01KMDKNFGN@?1?$AA@" +// CHECK: @"\01??_C@_01LFCBOECM@?4?$AA@" +// CHECK: @"\01??_C@_01JOAMLHOP@?9?$AA@" +// CHECK: @"\01??_C@_01IHBHIGKO@?0?$AA@" +// CHECK: @"\01??_C@_01MIFGBAGJ@?$CL?$AA@" +// CHECK: @"\01??_C@_01NBENCBCI@?$CK?$AA@" +// CHECK: @"\01??_C@_01PKGAHCOL@?$CJ?$AA@" +// CHECK: @"\01??_C@_01ODHLEDKK@?$CI?$AA@" +// CHECK: @"\01??_C@_01GEODFPGF@?8?$AA@" +// CHECK: @"\01??_C@_01HNPIGOCE@?$CG?$AA@" +// CHECK: @"\01??_C@_01FGNFDNOH@?$CF?$AA@" +// CHECK: @"\01??_C@_01EPMOAMKG@$?$AA@" +// CHECK: @"\01??_C@_01IPJKGB@?$CD?$AA@" +// CHECK: @"\01??_C@_01BJJEKLCA@?$CC?$AA@" +// CHECK: @"\01??_C@_01DCLJPIOD@?$CB?$AA@" +// CHECK: @"\01??_C@_01CLKCMJKC@?5?$AA@" +// CHECK: @"\01??_C@_01HDHMODJO@?$BP?$AA@" +// CHECK: @"\01??_C@_01GKGHNCNP@?$BO?$AA@" +// CHECK: @"\01??_C@_01EBEKIBBM@?$BN?$AA@" +// CHECK: @"\01??_C@_01FIFBLAFN@?$BM?$AA@" +// CHECK: @"\01??_C@_01BHBACGJK@?$BL?$AA@" +// CHECK: @"\01??_C@_01OALBHNL@?$BK?$AA@" +// CHECK: @"\01??_C@_01CFCGEEBI@?$BJ?$AA@" +// CHECK: @"\01??_C@_01DMDNHFFJ@?$BI?$AA@" +// CHECK: @"\01??_C@_01LLKFGJJG@?$BH?$AA@" +// CHECK: @"\01??_C@_01KCLOFINH@?$BG?$AA@" +// CHECK: @"\01??_C@_01IJJDALBE@?$BF?$AA@" +// CHECK: @"\01??_C@_01JAIIDKFF@?$BE?$AA@" +// CHECK: @"\01??_C@_01NPMJKMJC@?$BD?$AA@" +// CHECK: @"\01??_C@_01MGNCJNND@?$BC?$AA@" +// CHECK: @"\01??_C@_01ONPPMOBA@?$BB?$AA@" +// CHECK: @"\01??_C@_01PEOEPPFB@?$BA?$AA@" +// CHECK: @"\01??_C@_01DJLOPBMP@?$AP?$AA@" +// CHECK: @"\01??_C@_01CAKFMAIO@?$AO?$AA@" +// CHECK: @"\01??_C@_01LIIJDEN@?$AN?$AA@" +// CHECK: @"\01??_C@_01BCJDKCAM@?$AM?$AA@" +// CHECK: @"\01??_C@_01FNNCDEML@?$AL?$AA@" +// CHECK: @"\01??_C@_01EEMJAFIK@?6?$AA@" +// CHECK: @"\01??_C@_01GPOEFGEJ@?7?$AA@" +// CHECK: @"\01??_C@_01HGPPGHAI@?$AI?$AA@" +// CHECK: @"\01??_C@_01PBGHHLMH@?$AH?$AA@" +// CHECK: @"\01??_C@_01OIHMEKIG@?$AG?$AA@" +// CHECK: @"\01??_C@_01MDFBBJEF@?$AF?$AA@" +// CHECK: @"\01??_C@_01NKEKCIAE@?$AE?$AA@" +// CHECK: @"\01??_C@_01JFALLOMD@?$AD?$AA@" +// CHECK: @"\01??_C@_01IMBAIPIC@?$AC?$AA@" +// CHECK: @"\01??_C@_01KHDNNMEB@?$AB?$AA@" +// CHECK: @"\01??_C@_01LOCGONAA@?$AA?$AA@" + +const wchar_t *wl9 = L"\t"; +const wchar_t *wl10 = L"\n"; +const wchar_t *wl11 = L"\v"; +const wchar_t *wl32 = L" "; +const wchar_t *wl33 = L"!"; +const wchar_t *wl34 = L"\""; +const wchar_t *wl35 = L"#"; +const wchar_t *wl36 = L"$"; +const wchar_t *wl37 = L"%"; +const wchar_t *wl38 = L"&"; +const wchar_t *wl39 = L"'"; +const wchar_t *wl40 = L"("; +const wchar_t *wl41 = L")"; +const wchar_t *wl42 = L"*"; +const wchar_t *wl43 = L"+"; +const wchar_t *wl44 = L","; +const wchar_t *wl45 = L"-"; +const wchar_t *wl46 = L"."; +const wchar_t *wl47 = L"/"; +const wchar_t *wl48 = L"0"; +const wchar_t *wl49 = L"1"; +const wchar_t *wl50 = L"2"; +const wchar_t *wl51 = L"3"; +const wchar_t *wl52 = L"4"; +const wchar_t *wl53 = L"5"; +const wchar_t *wl54 = L"6"; +const wchar_t *wl55 = L"7"; +const wchar_t *wl56 = L"8"; +const wchar_t *wl57 = L"9"; +const wchar_t *wl58 = L":"; +const wchar_t *wl59 = L";"; +const wchar_t *wl60 = L"<"; +const wchar_t *wl61 = L"="; +const wchar_t *wl62 = L">"; +const wchar_t *wl63 = L"?"; +const wchar_t *wl64 = L"@"; +const wchar_t *wl65 = L"A"; +const wchar_t *wl66 = L"B"; +const wchar_t *wl67 = L"C"; +const wchar_t *wl68 = L"D"; +const wchar_t *wl69 = L"E"; +const wchar_t *wl70 = L"F"; +const wchar_t *wl71 = L"G"; +const wchar_t *wl72 = L"H"; +const wchar_t *wl73 = L"I"; +const wchar_t *wl74 = L"J"; +const wchar_t *wl75 = L"K"; +const wchar_t *wl76 = L"L"; +const wchar_t *wl77 = L"M"; +const wchar_t *wl78 = L"N"; +const wchar_t *wl79 = L"O"; +const wchar_t *wl80 = L"P"; +const wchar_t *wl81 = L"Q"; +const wchar_t *wl82 = L"R"; +const wchar_t *wl83 = L"S"; +const wchar_t *wl84 = L"T"; +const wchar_t *wl85 = L"U"; +const wchar_t *wl86 = L"V"; +const wchar_t *wl87 = L"W"; +const wchar_t *wl88 = L"X"; +const wchar_t *wl89 = L"Y"; +const wchar_t *wl90 = L"Z"; +const wchar_t *wl91 = L"["; +const wchar_t *wl92 = L"\\"; +const wchar_t *wl93 = L"]"; +const wchar_t *wl94 = L"^"; +const wchar_t *wl95 = L"_"; +const wchar_t *wl96 = L"`"; +const wchar_t *wl97 = L"a"; +const wchar_t *wl98 = L"b"; +const wchar_t *wl99 = L"c"; +const wchar_t *wl100 = L"d"; +const wchar_t *wl101 = L"e"; +const wchar_t *wl102 = L"f"; +const wchar_t *wl103 = L"g"; +const wchar_t *wl104 = L"h"; +const wchar_t *wl105 = L"i"; +const wchar_t *wl106 = L"j"; +const wchar_t *wl107 = L"k"; +const wchar_t *wl108 = L"l"; +const wchar_t *wl109 = L"m"; +const wchar_t *wl110 = L"n"; +const wchar_t *wl111 = L"o"; +const wchar_t *wl112 = L"p"; +const wchar_t *wl113 = L"q"; +const wchar_t *wl114 = L"r"; +const wchar_t *wl115 = L"s"; +const wchar_t *wl116 = L"t"; +const wchar_t *wl117 = L"u"; +const wchar_t *wl118 = L"v"; +const wchar_t *wl119 = L"w"; +const wchar_t *wl120 = L"x"; +const wchar_t *wl121 = L"y"; +const wchar_t *wl122 = L"z"; +const wchar_t *wl123 = L"{"; +const wchar_t *wl124 = L"|"; +const wchar_t *wl125 = L"}"; +const wchar_t *wl126 = L"~"; + +// CHECK: @"\01??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@" +// CHECK: @"\01??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@" +// CHECK: @"\01??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@" +// CHECK: @"\01??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@" +// CHECK: @"\01??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@" +// CHECK: @"\01??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@" +// CHECK: @"\01??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@" +// CHECK: @"\01??_C@_13PBOLBIIK@?$AA$?$AA?$AA@" +// CHECK: @"\01??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@" +// CHECK: @"\01??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@" +// CHECK: @"\01??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@" +// CHECK: @"\01??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@" +// CHECK: @"\01??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@" +// CHECK: @"\01??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@" +// CHECK: @"\01??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@" +// CHECK: @"\01??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@" +// CHECK: @"\01??_C@_13IMODFHAA@?$AA?9?$AA?$AA@" +// CHECK: @"\01??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@" +// CHECK: @"\01??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@" +// CHECK: @"\01??_C@_13COJANIEC@?$AA0?$AA?$AA@" +// CHECK: @"\01??_C@_13JGCMLPCH@?$AA1?$AA?$AA@" +// CHECK: @"\01??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@" +// CHECK: @"\01??_C@_13DMCFHHKM@?$AA3?$AA?$AA@" +// CHECK: @"\01??_C@_13KBPCEPBF@?$AA4?$AA?$AA@" +// CHECK: @"\01??_C@_13BJEOCIHA@?$AA5?$AA?$AA@" +// CHECK: @"\01??_C@_13LPLIHJO@?$AA6?$AA?$AA@" +// CHECK: @"\01??_C@_13LDEHOAPL@?$AA7?$AA?$AA@" +// CHECK: @"\01??_C@_13OLCEPAKN@?$AA8?$AA?$AA@" +// CHECK: @"\01??_C@_13FDJIJHMI@?$AA9?$AA?$AA@" +// CHECK: @"\01??_C@_13EBCNDICG@?$AA?3?$AA?$AA@" +// CHECK: @"\01??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@" +// CHECK: @"\01??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@" +// CHECK: @"\01??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@" +// CHECK: @"\01??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@" +// CHECK: @"\01??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@" +// CHECK: @"\01??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@" +// CHECK: @"\01??_C@_13PNBDBPLL@?$AAA?$AA?$AA@" +// CHECK: @"\01??_C@_13OPKGLAFF@?$AAB?$AA?$AA@" +// CHECK: @"\01??_C@_13FHBKNHDA@?$AAC?$AA?$AA@" +// CHECK: @"\01??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@" +// CHECK: @"\01??_C@_13HCHBIIOM@?$AAE?$AA?$AA@" +// CHECK: @"\01??_C@_13GAMECHAC@?$AAF?$AA?$AA@" +// CHECK: @"\01??_C@_13NIHIEAGH@?$AAG?$AA?$AA@" +// CHECK: @"\01??_C@_13IABLFADB@?$AAH?$AA?$AA@" +// CHECK: @"\01??_C@_13DIKHDHFE@?$AAI?$AA?$AA@" +// CHECK: @"\01??_C@_13CKBCJILK@?$AAJ?$AA?$AA@" +// CHECK: @"\01??_C@_13JCKOPPNP@?$AAK?$AA?$AA@" +// CHECK: @"\01??_C@_13PHJMHGG@?$AAL?$AA?$AA@" +// CHECK: @"\01??_C@_13LHMFKAAD@?$AAM?$AA?$AA@" +// CHECK: @"\01??_C@_13KFHAAPON@?$AAN?$AA?$AA@" +// CHECK: @"\01??_C@_13BNMMGIII@?$AAO?$AA?$AA@" +// CHECK: @"\01??_C@_13BFLGCPEB@?$AAP?$AA?$AA@" +// CHECK: @"\01??_C@_13KNAKEICE@?$AAQ?$AA?$AA@" +// CHECK: @"\01??_C@_13LPLPOHMK@?$AAR?$AA?$AA@" +// CHECK: @"\01??_C@_13HADIAKP@?$AAS?$AA?$AA@" +// CHECK: @"\01??_C@_13JKNELIBG@?$AAT?$AA?$AA@" +// CHECK: @"\01??_C@_13CCGINPHD@?$AAU?$AA?$AA@" +// CHECK: @"\01??_C@_13DANNHAJN@?$AAV?$AA?$AA@" +// CHECK: @"\01??_C@_13IIGBBHPI@?$AAW?$AA?$AA@" +// CHECK: @"\01??_C@_13NAACAHKO@?$AAX?$AA?$AA@" +// CHECK: @"\01??_C@_13GILOGAML@?$AAY?$AA?$AA@" +// CHECK: @"\01??_C@_13HKALMPCF@?$AAZ?$AA?$AA@" +// CHECK: @"\01??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@" +// CHECK: @"\01??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@" +// CHECK: @"\01??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@" +// CHECK: @"\01??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@" +// CHECK: @"\01??_C@_13ENNFDPBH@?$AA_?$AA?$AA@" +// CHECK: @"\01??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@" +// CHECK: @"\01??_C@_13FNCBLAIF@?$AAa?$AA?$AA@" +// CHECK: @"\01??_C@_13EPJEBPGL@?$AAb?$AA?$AA@" +// CHECK: @"\01??_C@_13PHCIHIAO@?$AAc?$AA?$AA@" +// CHECK: @"\01??_C@_13GKPPEALH@?$AAd?$AA?$AA@" +// CHECK: @"\01??_C@_13NCEDCHNC@?$AAe?$AA?$AA@" +// CHECK: @"\01??_C@_13MAPGIIDM@?$AAf?$AA?$AA@" +// CHECK: @"\01??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@" +// CHECK: @"\01??_C@_13CACJPPAP@?$AAh?$AA?$AA@" +// CHECK: @"\01??_C@_13JIJFJIGK@?$AAi?$AA?$AA@" +// CHECK: @"\01??_C@_13IKCADHIE@?$AAj?$AA?$AA@" +// CHECK: @"\01??_C@_13DCJMFAOB@?$AAk?$AA?$AA@" +// CHECK: @"\01??_C@_13KPELGIFI@?$AAl?$AA?$AA@" +// CHECK: @"\01??_C@_13BHPHAPDN@?$AAm?$AA?$AA@" +// CHECK: @"\01??_C@_13FECKAND@?$AAn?$AA?$AA@" +// CHECK: @"\01??_C@_13LNPOMHLG@?$AAo?$AA?$AA@" +// CHECK: @"\01??_C@_13LFIEIAHP@?$AAp?$AA?$AA@" +// CHECK: @"\01??_C@_13NDIOHBK@?$AAq?$AA?$AA@" +// CHECK: @"\01??_C@_13BPINEIPE@?$AAr?$AA?$AA@" +// CHECK: @"\01??_C@_13KHDBCPJB@?$AAs?$AA?$AA@" +// CHECK: @"\01??_C@_13DKOGBHCI@?$AAt?$AA?$AA@" +// CHECK: @"\01??_C@_13ICFKHAEN@?$AAu?$AA?$AA@" +// CHECK: @"\01??_C@_13JAOPNPKD@?$AAv?$AA?$AA@" +// CHECK: @"\01??_C@_13CIFDLIMG@?$AAw?$AA?$AA@" +// CHECK: @"\01??_C@_13HADAKIJA@?$AAx?$AA?$AA@" +// CHECK: @"\01??_C@_13MIIMMPPF@?$AAy?$AA?$AA@" +// CHECK: @"\01??_C@_13NKDJGABL@?$AAz?$AA?$AA@" +// CHECK: @"\01??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@" +// CHECK: @"\01??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@" +// CHECK: @"\01??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@" +// CHECK: @"\01??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@" + +const char *LongASCIIString = "012345678901234567890123456789ABCDEF"; +// CHECK: @"\01??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@" +const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF"; +// CHECK: @"\01??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@" +const wchar_t *UnicodeLiteral = L"\ud7ff"; +// CHECK: @"\01??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@" diff --git a/test/CodeGenCXX/mangle-ms-template-callback.cpp b/test/CodeGenCXX/mangle-ms-template-callback.cpp index 687814875132b..1a8f82fc82566 100644 --- a/test/CodeGenCXX/mangle-ms-template-callback.cpp +++ b/test/CodeGenCXX/mangle-ms-template-callback.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s template<typename Signature> class C; @@ -70,3 +70,20 @@ void call_bar() { // CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z" // FYI blocks are not present in MSVS, so we're free to choose the spec. } + +template <void (*Fn)()> void WrapFnPtr() { Fn(); } +template <void (&Fn)()> void WrapFnRef() { Fn(); } +struct Thing { + static void VoidStaticMethod(); +}; +void VoidFn(); +void CallWrapper() { + WrapFnPtr<VoidFn>(); + WrapFnRef<VoidFn>(); + WrapFnPtr<Thing::VoidStaticMethod>(); + WrapFnRef<Thing::VoidStaticMethod>(); +} +// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ" +// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ" +// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ" +// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ" diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp new file mode 100644 index 0000000000000..e2cbe15dfa9ff --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -Wno-microsoft -fms-extensions -fno-rtti -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s + +template <typename T, int (T::*)() = nullptr> +struct J {}; + +struct __single_inheritance M; +J<M> m; +// CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A" + +struct __multiple_inheritance N; +J<N> n; +// CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A" + +struct __virtual_inheritance O; +J<O> o; +// CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A" + +struct P; +J<P> p; +// CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A" + +#pragma pointers_to_members(full_generality, virtual_inheritance) + +struct S { + int a, b; + void f(); + virtual void g(); +}; + +struct GeneralBase { + virtual void h(); +}; +struct MostGeneral : S, virtual GeneralBase { + virtual void h(); +}; +template <void (MostGeneral::*MP)()> +struct ClassTemplate { + ClassTemplate() {} +}; + +template struct ClassTemplate<&MostGeneral::h>; + +// Test that we mangle in the vbptr offset, which is 12 here. +// +// CHECK: define weak_odr x86_thiscallcc %struct.ClassTemplate* @"\01??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ" diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp new file mode 100644 index 0000000000000..803cac3748b1c --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp @@ -0,0 +1,143 @@ +// RUN: %clang_cc1 -Wno-microsoft -fno-rtti -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s + +struct U; +static_assert(sizeof(void (U::*)()) == 2 * sizeof(void*) + 2 * sizeof(int), ""); + +struct A { int a; }; +struct B { int b; }; +struct I { union { struct { int a, b; }; }; }; + +struct S { int a, b; void f(); virtual void g(); }; +struct M : A, B { int a, b; void f(); virtual void g(); }; +struct V : virtual A { int a, b; void f(); virtual void g(); }; +struct U { int a, b; void f(); virtual void g(); }; + +struct C { virtual void f(); }; +struct D { virtual void g(); }; +struct O : C, D { virtual void g(); }; // override of non-primary + +// Test data member pointers. +template <typename T, int T::*F> +int ReadField(T &o) { + return F ? o.*F : 0; +} + +// Redeclare some of the classes so that the implicit attribute goes on the most +// recent redeclaration rather than the definition. +struct V; + +void ReadFields() { + A a; + I i; + S s; + M m; + V v; + U u; + ReadField<S, &S::a>(s); + ReadField<M, &M::a>(m); + ReadField<V, &V::a>(v); + ReadField<U, &U::a>(u); + ReadField<S, &S::b>(s); + ReadField<M, &M::b>(m); + ReadField<V, &V::b>(v); + ReadField<U, &U::b>(u); + ReadField<S, nullptr>(s); + ReadField<M, nullptr>(m); + ReadField<V, nullptr>(v); + ReadField<U, nullptr>(u); + + // Non-polymorphic null data memptr vs first field memptr. + ReadField<A, &A::a>(a); + ReadField<A, nullptr>(a); + + // Indirect fields injected from anonymous unions and structs + ReadField<I, &I::a>(i); + ReadField<I, &I::b>(i); +} + +// CHECK-LABEL: define {{.*}}ReadFields +// CHECK: call {{.*}} @"\01??$ReadField@US@@$03@@YAHAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0M@@@YAHAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@US@@$07@@YAHAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z" + +// MSVC mangles null member pointers in function templates wrong, but it gets +// them right in class templates. +// CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FA@?0@@YAHAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UU@@$GA@A@?0@@YAHAAUU@@@Z" + +// Non-polymorphic null data memptr vs first field memptr. MSVC mangles these +// the same. +// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0A@@@YAHAAUA@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0?0@@YAHAAUA@@@Z" + +// Indirect fields are handled as-if they were simply members of their enclosing +// record. +// CHECK: call {{.*}} @"\01??$ReadField@UI@@$0A@@@YAHAAUI@@@Z" +// CHECK: call {{.*}} @"\01??$ReadField@UI@@$03@@YAHAAUI@@@Z" + +// Test member function pointers. +template <typename T, void (T::*MFP)()> +void CallMethod(T &o) { + (o.*MFP)(); +} + +void CallMethods() { + S s; + M m; + V v; + U u; + O o; + + // Non-virtual methods. + CallMethod<S, &S::f>(s); + CallMethod<M, &M::f>(m); + CallMethod<V, &V::f>(v); + CallMethod<U, &U::f>(u); + + // Virtual methods requiring thunk mangling. + CallMethod<S, &S::g>(s); + CallMethod<M, &M::g>(m); + CallMethod<V, &V::g>(v); + CallMethod<U, &U::g>(u); + + // A member pointer for a non-primary vbase will have a non-zero this + // adjustment. + CallMethod<O, &O::g>(o); + + // Null member pointers. + CallMethod<S, nullptr>(s); + CallMethod<M, nullptr>(m); + CallMethod<V, nullptr>(v); + CallMethod<U, nullptr>(u); +} + +// CHECK-LABEL: define {{.*}}CallMethods +// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z" + +// PR17034: MSVC reuses the same thunk for every virtual g method because they +// are all at vftable offset zero. They then mangle the name of the first thunk +// created into the name of the template instantiation, which is definitely a +// bug. We don't follow them here. Instead of ?_91@ backref below, they would +// get ?_9S@@ in every instantiation after the first. + +// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z" + +// CHECK: call {{.*}} @"\01??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z" + +// CHECK: call {{.*}} @"\01??$CallMethod@US@@$0A@@@YAXAAUS@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z" +// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z" diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp index 514f5739ffd5b..31fda2046c4bc 100644 --- a/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s template<typename T> class Class { @@ -262,3 +262,17 @@ void CallFunctionDefinedWithInjectedName() { FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>()); } // CHECK: @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z" + +// We need to be able to feed GUIDs through a couple rounds of template +// substitution. +template <const _GUID *G> +struct UUIDType3 { + void foo() {} +}; +template <const _GUID *G> +struct UUIDType4 : UUIDType3<G> { + void bar() { UUIDType4::foo(); } +}; +template struct UUIDType4<&__uuidof(uuid)>; +// CHECK: "\01?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ" +// CHECK: "\01?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ" diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp index 64cb7250a41fe..aca492918a1e7 100644 --- a/test/CodeGenCXX/mangle-ms-vector-types.cpp +++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -cxx-abi microsoft -triple=i686-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s #include <xmmintrin.h> #include <emmintrin.h> diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 68ec2b3baf68b..3285c98546ec8 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -std=c++11 | FileCheck %s -// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 -std=c++11| FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 -std=c++98 | FileCheck %s +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s int a; // CHECK-DAG: @"\01?a@@3HA" @@ -95,10 +95,18 @@ extern int * const h1 = &a; // CHECK-DAG: @"\01?h1@@3QAHA" extern const int * const h2 = &a; // CHECK-DAG: @"\01?h2@@3QBHB" +extern int * const __restrict h3 = &a; +// CHECK-DAG: @"\01?h3@@3QIAHIA" +// X64-DAG: @"\01?h3@@3QEIAHEIA" int i[10][20]; // CHECK-DAG: @"\01?i@@3PAY0BE@HA" +typedef int (*FunT)(int, int); +FunT FunArr[10][20]; +// CHECK-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA" +// X64-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA" + int (__stdcall *j)(signed char, unsigned char); // CHECK-DAG: @"\01?j@@3P6GHCE@ZA" @@ -357,10 +365,3 @@ void TypedefNewDelete::operator delete[](void *) { } // CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z // CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z -namespace PR18022 { - -struct { } a; -decltype(a) fun(decltype(a) x, decltype(a)) { return x; } -// CHECK-DAG: ?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z - -} diff --git a/test/CodeGenCXX/mangle-neon-vectors.cpp b/test/CodeGenCXX/mangle-neon-vectors.cpp index 249ec2e99b694..6faf6226efd2e 100644 --- a/test/CodeGenCXX/mangle-neon-vectors.cpp +++ b/test/CodeGenCXX/mangle-neon-vectors.cpp @@ -1,10 +1,18 @@ -// RUN: %clang_cc1 -triple arm-none-linux-gnueabi -target-feature +neon %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple armv7-apple-ios -target-feature +neon %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios -target-feature +neon %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-AARCH64 typedef float float32_t; +typedef double float64_t; typedef __fp16 float16_t; +#if defined(__aarch64__) +typedef unsigned char poly8_t; +typedef unsigned short poly16_t; +#else typedef signed char poly8_t; typedef short poly16_t; -typedef unsigned long long uint64_t; +#endif +typedef unsigned __INT64_TYPE__ uint64_t; typedef __attribute__((neon_vector_type(2))) int int32x2_t; typedef __attribute__((neon_vector_type(4))) int int32x4_t; @@ -14,26 +22,53 @@ typedef __attribute__((neon_vector_type(2))) float32_t float32x2_t; typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t; typedef __attribute__((neon_vector_type(4))) float16_t float16x4_t; typedef __attribute__((neon_vector_type(8))) float16_t float16x8_t; -typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t; -typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t; +#ifdef __aarch64__ +typedef __attribute__((neon_vector_type(2))) float64_t float64x2_t; +#endif +typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t; +typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t; // CHECK: 16__simd64_int32_t +// CHECK-AARCH64: 11__Int32x2_t void f1(int32x2_t v) { } + // CHECK: 17__simd128_int32_t +// CHECK-AARCH64: 11__Int32x4_t void f2(int32x4_t v) { } + // CHECK: 17__simd64_uint64_t +// CHECK-AARCH64: 12__Uint64x1_t void f3(uint64x1_t v) { } + // CHECK: 18__simd128_uint64_t +// CHECK-AARCH64: 12__Uint64x2_t void f4(uint64x2_t v) { } + // CHECK: 18__simd64_float32_t +// CHECK-AARCH64: 13__Float32x2_t void f5(float32x2_t v) { } + // CHECK: 19__simd128_float32_t +// CHECK-AARCH64: 13__Float32x4_t void f6(float32x4_t v) { } + // CHECK: 18__simd64_float16_t +// CHECK-AARCH64: 13__Float16x4_t void f7(float16x4_t v) {} + // CHECK: 19__simd128_float16_t +// CHECK-AARCH64: 13__Float16x8_t void f8(float16x8_t v) {} + // CHECK: 17__simd128_poly8_t +// CHECK-AARCH64: 12__Poly8x16_t void f9(poly8x16_t v) {} + // CHECK: 18__simd128_poly16_t +// CHECK-AARCH64: 12__Poly16x8_t void f10(poly16x8_t v) {} + +#ifdef __aarch64__ +// CHECK-AARCH64: 13__Float64x2_t +void f11(float64x2_t v) { } +#endif diff --git a/test/CodeGenCXX/mangle-nullptr-arg.cpp b/test/CodeGenCXX/mangle-nullptr-arg.cpp index b55ea6dd2dd43..66ed7e5cfe342 100644 --- a/test/CodeGenCXX/mangle-nullptr-arg.cpp +++ b/test/CodeGenCXX/mangle-nullptr-arg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s template<int *ip> struct IP {}; diff --git a/test/CodeGenCXX/mangle-std-externc.cpp b/test/CodeGenCXX/mangle-std-externc.cpp index a478dee4a42c7..f0c7d69eed469 100644 --- a/test/CodeGenCXX/mangle-std-externc.cpp +++ b/test/CodeGenCXX/mangle-std-externc.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -DNS=std -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-STD -// RUN: %clang_cc1 %s -DNS=n -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-N +// RUN: %clang_cc1 %s -DNS=std -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s --check-prefix=CHECK-STD +// RUN: %clang_cc1 %s -DNS=n -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s --check-prefix=CHECK-N // _ZNSt1DISt1CE1iE = std::D<std::C>::i // CHECK-STD: @_ZNSt1DISt1CE1iE = diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp index 6277c7af21c47..678956e11182a 100644 --- a/test/CodeGenCXX/mangle-subst-std.cpp +++ b/test/CodeGenCXX/mangle-subst-std.cpp @@ -15,8 +15,8 @@ namespace std { struct A { A(); }; - // CHECK-LABEL: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr // CHECK-LABEL: define void @_ZNSt1AC2Ev(%"struct.std::A"* %this) unnamed_addr + // CHECK-LABEL: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr A::A() { } }; diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp index 3b7f3027f6c24..998096a57be4c 100644 --- a/test/CodeGenCXX/mangle-template.cpp +++ b/test/CodeGenCXX/mangle-template.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s +// expected-no-diagnostics + namespace test1 { int x; template <int& D> class T { }; @@ -145,7 +147,7 @@ namespace test10 { } } -// Report from Jason Merrill on cxx-abi-dev, 2012.01.04. +// Report from cxx-abi-dev, 2012.01.04. namespace test11 { int cmp(char a, char b); template <typename T, int (*cmp)(T, T)> struct A {}; @@ -156,7 +158,7 @@ namespace test11 { namespace test12 { // Make sure we can mangle non-type template args with internal linkage. - static int f(); + static int f() {} const int n = 10; template<typename T, T v> void test() {} void use() { @@ -182,3 +184,25 @@ namespace test13 { template short returnShort<-32768>(); // CHECK: @_ZN6test1311returnShortILsn32768EEEsv() } + +namespace test14 { + template <typename> inline int inl(bool b) { + if (b) { + static struct { + int field; + } a; + // CHECK: @_ZZN6test143inlIvEEibE1a + + return a.field; + } else { + static struct { + int field; + } a; + // CHECK: @_ZZN6test143inlIvEEibE1a_0 + + return a.field; + } + } + + int call(bool b) { return inl<void>(b); } +} diff --git a/test/CodeGenCXX/mangle-windows.cpp b/test/CodeGenCXX/mangle-windows.cpp index c087616875c79..85644475ddf5b 100644 --- a/test/CodeGenCXX/mangle-windows.cpp +++ b/test/CodeGenCXX/mangle-windows.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft \ -// RUN: -triple=i386-pc-win32 | FileCheck --check-prefix=WIN %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | \ +// RUN: FileCheck --check-prefix=WIN %s // // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | \ // RUN: FileCheck --check-prefix=ITANIUM %s diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index d836f36c1818b..9bdac7f17289f 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -216,9 +216,9 @@ struct S7 { }; // PR5139 -// CHECK: @_ZN2S7C1Ev // CHECK: @_ZN2S7C2Ev // CHECK: @_ZN2S7Ut_C1Ev +// CHECK: @_ZN2S7C1Ev S7::S7() {} // PR5063 @@ -280,13 +280,13 @@ struct Ops { void *v; }; -// CHECK-LABEL: define %struct.Ops* @_ZN3OpsplERKS_ +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsplERKS_ Ops& Ops::operator+(const Ops&) { return *this; } -// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmiERKS_ +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsmiERKS_ Ops& Ops::operator-(const Ops&) { return *this; } -// CHECK-LABEL: define %struct.Ops* @_ZN3OpsanERKS_ +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsanERKS_ Ops& Ops::operator&(const Ops&) { return *this; } -// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmlERKS_ +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsmlERKS_ Ops& Ops::operator*(const Ops&) { return *this; } // PR5861 @@ -899,7 +899,7 @@ namespace test39 { } namespace test40 { - // CHECK: i32* @_ZZN6test401fEvE1a_0 + // CHECK: i32* {{.*}} @_ZZN6test401fEvE1a_0 void h(int&); inline void f() { if (0) { @@ -951,3 +951,43 @@ namespace test44 { } // CHECK-LABEL: define linkonce_odr void @_ZN6test443foo3barEv(%"struct.test44::foo"* %this) } + +namespace test45 { + struct S { + enum e {}; + }; + template <typename T> + void f(enum T::e *) {} + template void f<S>(S::e *); + // CHECK-LABEL: define weak_odr void @_ZN6test451fINS_1SEEEvPTeNT_1eE(i32*) +} + +namespace test46 { + struct S { + struct s {}; + }; + template <typename T> + void f(struct T::s *) {} + template void f<S>(S::s *); + // CHECK-LABEL: define weak_odr void @_ZN6test461fINS_1SEEEvPTsNT_1sE(%"struct.test46::S::s"*) +} + +namespace test47 { + struct S { + class c {}; + }; + template <typename T> + void f(class T::c *) {} + template void f<S>(S::c *); + // CHECK-LABEL: define weak_odr void @_ZN6test471fINS_1SEEEvPTsNT_1cE(%"class.test47::S::c"*) +} + +namespace test48 { + struct S { + union u {}; + }; + template <typename T> + void f(union T::u *) {} + template void f<S>(S::u *); + // CHECK-LABEL: define weak_odr void @_ZN6test481fINS_1SEEEvPTuNT_1uE(%"union.test48::S::u"*) +} diff --git a/test/CodeGenCXX/member-alignment.cpp b/test/CodeGenCXX/member-alignment.cpp index 78026d4e0419c..43ed5e28e8843 100644 --- a/test/CodeGenCXX/member-alignment.cpp +++ b/test/CodeGenCXX/member-alignment.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s // rdar://7268289 diff --git a/test/CodeGenCXX/member-function-pointer-calls.cpp b/test/CodeGenCXX/member-function-pointer-calls.cpp index 99162ebd5863b..67417ef046930 100644 --- a/test/CodeGenCXX/member-function-pointer-calls.cpp +++ b/test/CodeGenCXX/member-function-pointer-calls.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-windows-gnu -emit-llvm -o - | FileCheck %s -check-prefix MINGW64 struct A { virtual int vf1() { return 1; } virtual int vf2() { return 2; } @@ -10,6 +11,8 @@ int f(A* a, int (A::*fp)()) { // CHECK-LABEL: define i32 @_Z2g1v() // CHECK: ret i32 1 +// MINGW64-LABEL: define i32 @_Z2g1v() +// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}}) int g1() { A a; return f(&a, &A::vf1); @@ -17,6 +20,8 @@ int g1() { // CHECK-LABEL: define i32 @_Z2g2v() // CHECK: ret i32 2 +// MINGW64-LABEL: define i32 @_Z2g2v() +// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}}) int g2() { A a; return f(&a, &A::vf2); diff --git a/test/CodeGenCXX/member-init-anon-union.cpp b/test/CodeGenCXX/member-init-anon-union.cpp index bfe1667c8c6ce..b488fa763d647 100644 --- a/test/CodeGenCXX/member-init-anon-union.cpp +++ b/test/CodeGenCXX/member-init-anon-union.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s // PR10531. @@ -21,12 +21,42 @@ int g() { int a; int b = 81; }; - // CHECK: define {{.*}}_Z1gv + // CHECK-LABEL: define {{.*}}_Z1gv // CHECK-NOT: } // CHECK: call {{.*}}@"[[CONSTRUCT_LOCAL:.*]]C1Ev" return b; } +struct A { + A(); +}; +union B { + int k; + struct { + A x; + int y = 123; + }; + B() {} + B(int n) : k(n) {} +}; + +B b1; +B b2(0); + + +// CHECK-LABEL: define {{.*}} @_ZN1BC2Ei( +// CHECK-NOT: call void @_ZN1AC1Ev( +// CHECK-NOT: store i32 123, +// CHECK: store i32 % +// CHECK-NOT: call void @_ZN1AC1Ev( +// CHECK-NOT: store i32 123, +// CHECK: } + +// CHECK-LABEL: define {{.*}} @_ZN1BC2Ev( +// CHECK: call void @_ZN1AC1Ev( +// CHECK: store i32 123, +// CHECK: } + // CHECK: define {{.*}}@"[[CONSTRUCT_LOCAL]]C2Ev" // CHECK-NOT: } diff --git a/test/CodeGenCXX/member-templates.cpp b/test/CodeGenCXX/member-templates.cpp index c72dd6e5f5289..93d36ff4750ac 100644 --- a/test/CodeGenCXX/member-templates.cpp +++ b/test/CodeGenCXX/member-templates.cpp @@ -15,8 +15,8 @@ struct B { template<typename T> B::B(T) {} -// CHECK-LABEL: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) unnamed_addr // CHECK-LABEL: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32) unnamed_addr +// CHECK-LABEL: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) unnamed_addr template B::B(int); template<typename T> diff --git a/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp b/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp index 7407efed2f9d1..c8477f4cbdd32 100644 --- a/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp +++ b/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s -// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s -check-prefix CHECK-X64 +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s -check-prefix CHECK-X64 struct B { char a; }; struct A : virtual B {} a; // The <> indicate that the pointer is packed, which is required to support // microsoft layout in 32 bit mode, but not 64 bit mode. -// CHECK: %struct.A = type <{ i32*, %struct.B }>
-// CHECK-X64: %struct.A = type { i32*, %struct.B }
+// CHECK: %struct.A = type <{ i32*, %struct.B }> +// CHECK-X64: %struct.A = type { i32*, %struct.B } diff --git a/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/test/CodeGenCXX/microsoft-abi-arg-order.cpp new file mode 100644 index 0000000000000..b47508b302d1c --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-arg-order.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s -check-prefix=X86 +// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s -check-prefix=X64 + +struct A { + A(int a); + A(const A &o); + ~A(); + int a; +}; + +void foo(A a, A b, A c) { +} + +// Order of destruction should be left to right. +// +// X86-LABEL: define void @"\01?foo@@YAXUA@@00@Z" +// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca) +// X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 0 +// X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 1 +// X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 2 +// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]]) +// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[b]]) +// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]]) +// X86: ret void + +// X64-LABEL: define void @"\01?foo@@YAXUA@@00@Z" +// X64: (%struct.A* %[[a:[^,]*]], %struct.A* %[[b:[^,]*]], %struct.A* %[[c:[^)]*]]) +// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[a]]) +// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[b]]) +// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[c]]) +// X64: ret void + + +void call_foo() { + foo(A(1), A(2), A(3)); +} + +// Order of evaluation should be right to left, and we should clean up the right +// things as we unwind. +// +// X86-LABEL: define void @"\01?call_foo@@YAXXZ"() +// X86: call i8* @llvm.stacksave() +// X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]] +// X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 2 +// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3) +// X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 +// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2) +// X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 +// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1) +// X86: invoke void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// X86: call void @llvm.stackrestore +// X86: ret void +// +// lpad2: +// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]]) +// X86: br label +// +// ehcleanup: +// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg3]]) + +// X64-LABEL: define void @"\01?call_foo@@YAXXZ"() +// X64: call %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3) +// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2) +// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1) +// X64: call void @"\01?foo@@YAXUA@@00@Z" +// X64: (%struct.A* %[[arg1]], %struct.A* %[[arg2]], %struct.A* %[[arg3]]) +// X64: ret void +// +// lpad2: +// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]]) +// X64: br label +// +// ehcleanup: +// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg3]]) diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp index 1ba1f6a5f2787..8da4fcf213822 100644 --- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp +++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s struct ClassWithoutDtor { char x; diff --git a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp new file mode 100644 index 0000000000000..985b1ce62e924 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s + +struct A { + A() : a(42) {} + A(const A &o) : a(o.a) {} + ~A() {} + int a; + A foo(A o); +}; + +A A::foo(A x) { + A y(*this); + y.a += x.a; + return y; +} + +// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z" +// CHECK: (%struct.A* %this, <{ %struct.A*, %struct.A }>* inalloca) +// CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0 +// CHECK: load %struct.A** +// CHECK: ret %struct.A* + +int main() { + A x; + A y = x.foo(x); +} + +// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z" +// CHECK: (%struct.A* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) diff --git a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp new file mode 100644 index 0000000000000..6a0a8601c0cc2 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -Wno-non-pod-varargs -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s + +#include <stdarg.h> + +struct A { + A(int a) : a(a) {} + A(const A &o) : a(o.a) {} + ~A() {} + int a; +}; + +int foo(A a, ...) { + va_list ap; + va_start(ap, a); + int sum = 0; + for (int i = 0; i < a.a; ++i) + sum += va_arg(ap, int); + va_end(ap); + return sum; +} + +// CHECK-LABEL: define i32 @"\01?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...) + +int main() { + return foo(A(3), 1, 2, 3); +} +// CHECK-LABEL: define i32 @main() +// CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }> +// CHECK: call i32 {{.*bitcast.*}}@"\01?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]]) + +void varargs_zero(...); +void varargs_one(int, ...); +void varargs_two(int, int, ...); +void varargs_three(int, int, int, ...); +void call_var_args() { + A x(3); + varargs_zero(x); + varargs_one(1, x); + varargs_two(1, 2, x); + varargs_three(1, 2, 3, x); +} + +// CHECK-LABEL: define void @"\01?call_var_args@@YAXXZ"() +// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}}) + +// CHECK-LABEL: declare void @"\01?varargs_zero@@YAXZZ"(...) +// CHECK-LABEL: declare void @"\01?varargs_one@@YAXHZZ"(i32, ...) +// CHECK-LABEL: declare void @"\01?varargs_two@@YAXHHZZ"(i32, i32, ...) +// CHECK-LABEL: declare void @"\01?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...) diff --git a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp new file mode 100644 index 0000000000000..da58c461dcc09 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm %s -o - | FileCheck %s + +// PR15768 + +// A trivial 12 byte struct is returned indirectly. +struct S { + S(); + int a, b, c; +}; + +struct C { + S variadic_sret(const char *f, ...); + S __cdecl cdecl_sret(); + S __cdecl byval_and_sret(S a); + int c; +}; + +S C::variadic_sret(const char *f, ...) { return S(); } +S C::cdecl_sret() { return S(); } +S C::byval_and_sret(S a) { return S(); } + +// CHECK: define void @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...) +// CHECK: define void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result) +// CHECK: define void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a) + +int main() { + C c; + c.variadic_sret("asdf"); + c.cdecl_sret(); + c.byval_and_sret(S()); +} +// CHECK-LABEL: define i32 @main() +// CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ" +// CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ" +// CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z" + +// __fastcall has similar issues. +struct A { + S __fastcall f(int x); +}; +S A::f(int x) { + return S(); +} +// CHECK-LABEL: define x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x) diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp index 92db9a789b3c3..319f39c3ff480 100644 --- a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s struct A { constexpr A(int x) : x(x) {} diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp index d7fba9911e1ba..e3ca39221e88d 100644 --- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp +++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck -check-prefix GCABI %s -// RUN: %clang_cc1 -emit-llvm %s -o - -DMS_ABI -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck -check-prefix MSABI %s +// RUN: %clang_cc1 -triple i386-pc-linux -emit-llvm %s -o - | FileCheck -check-prefix GCABI %s +// RUN: %clang_cc1 -emit-llvm %s -o - -DMS_ABI -triple=i386-pc-win32 | FileCheck -check-prefix MSABI %s #ifdef MS_ABI # define METHOD_CC __thiscall diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp new file mode 100644 index 0000000000000..225407b7fa9cb --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -0,0 +1,130 @@ +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s + +struct S { char a; }; +struct V { virtual void f(); }; +struct A : virtual V {}; +struct B : S, virtual V {}; +struct T {}; + +T* test0() { return dynamic_cast<T*>((B*)0); } +// CHECK-LABEL: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"() +// CHECK: ret %struct.T* null + +T* test1(V* x) { return &dynamic_cast<T&>(*x); } +// CHECK-LABEL: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x) +// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8* +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* +// CHECK-NEXT: ret %struct.T* [[RET]] + +T* test2(A* x) { return &dynamic_cast<T&>(*x); } +// CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) +// CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8* +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[VBOFFS]] +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* +// CHECK-NEXT: ret %struct.T* [[RET]] + +T* test3(B* x) { return &dynamic_cast<T&>(*x); } +// CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) +// CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 +// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 4 +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], 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 1) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* +// CHECK-NEXT: ret %struct.T* [[RET]] + +T* test4(V* x) { return dynamic_cast<T*>(x); } +// CHECK-LABEL: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x) +// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8* +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* +// CHECK-NEXT: ret %struct.T* [[RET]] + +T* test5(A* x) { return dynamic_cast<T*>(x); } +// CHECK-LABEL: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) +// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null +// CHECK-NEXT: br i1 [[CHECK]] +// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@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* +// CHECK-NEXT: ret %struct.T* [[RET]] + +T* test6(B* x) { return dynamic_cast<T*>(x); } +// CHECK-LABEL: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) +// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null +// CHECK-NEXT: br i1 [[CHECK]] +// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 +// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds 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: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* +// CHECK-NEXT: br label +// CHECK: [[RET:%.*]] = phi %struct.T* +// CHECK-NEXT: ret %struct.T* [[RET]] + +void* test7(V* x) { return dynamic_cast<void*>(x); } +// CHECK-LABEL: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x) +// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8* +// CHECK-NEXT: [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8* [[CAST]]) +// CHECK-NEXT: ret i8* [[RET]] + +void* test8(A* x) { return dynamic_cast<void*>(x); } +// CHECK-LABEL: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x) +// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null +// CHECK-NEXT: br i1 [[CHECK]] +// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] +// CHECK-NEXT: [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) +// CHECK-NEXT: br label +// CHECK: [[RET:%.*]] = phi i8* +// CHECK-NEXT: ret i8* [[RET]] + +void* test9(B* x) { return dynamic_cast<void*>(x); } +// CHECK-LABEL: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x) +// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null +// CHECK-NEXT: br i1 [[CHECK]] +// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 +// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 +// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]] +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) +// CHECK-NEXT: br label +// CHECK: [[RET:%.*]] = phi i8* +// CHECK-NEXT: ret i8* [[RET]] + diff --git a/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/test/CodeGenCXX/microsoft-abi-exceptions.cpp index 7757ea0043599..60a3514c640af 100644 --- a/test/CodeGenCXX/microsoft-abi-exceptions.cpp +++ b/test/CodeGenCXX/microsoft-abi-exceptions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s struct A { A(); @@ -14,17 +14,21 @@ void HasEHCleanup() { } // With exceptions, we need to clean up at least one of these temporaries. -// WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { -// First one doesn't have any cleanups, no need for invoke. -// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) +// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { +// WIN32: %[[base:.*]] = call i8* @llvm.stacksave() +// If this call throws, we have to restore the stack. +// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) // If this call throws, we have to cleanup the first temporary. // WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) -// If this call throws, we already popped our cleanups -// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// If this call throws, we have to cleanup the stacksave. +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call void @llvm.stackrestore(i8* %[[base]]) // WIN32: ret void // // There should be one dtor call for unwinding from the second getA. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-NOT: @"\01??1A@@QAE@XZ" +// WIN32: call void @llvm.stackrestore // WIN32: } void TakeRef(const A &a); @@ -32,20 +36,28 @@ int HasDeactivatedCleanups() { return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())); } -// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { +// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { // WIN32: %[[isactive:.*]] = alloca i1 -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: call i8* @llvm.stacksave() +// WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]] +// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) +// +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: store i1 true, i1* %[[isactive]] +// +// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 false, i1* %[[isactive]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// WIN32: call void @llvm.stackrestore // Destroy the two const ref temporaries. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Conditionally destroy arg1. @@ -60,20 +72,22 @@ int HasConditionalCleanup(bool cond) { return (cond ? TakesTwo(A(), A()) : CouldThrow()); } -// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { +// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { // WIN32: store i1 false // WIN32: br i1 -// No cleanups, so we call and then activate a cleanup if it succeeds. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) +// WIN32: call i8* @llvm.stacksave() +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) // WIN32: store i1 true -// Now we have a cleanup for the first aggregate, so we invoke. // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) -// Now we have no cleanups because TakeTwo will destruct both args. -// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" -// Still no cleanups, so call. +// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call void @llvm.stackrestore +// // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() -// Somewhere in the landing pad for our single invoke, call the dtor. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// +// Only one dtor in the invoke for arg1 +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call void @llvm.stackrestore // WIN32: } // Now test both. @@ -81,8 +95,7 @@ int HasConditionalDeactivatedCleanups(bool cond) { return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: %[[arg1:.*]] = alloca %struct.A, align 4 +// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { // WIN32: alloca i1 // WIN32: %[[arg1_cond:.*]] = alloca i1 // Start all four cleanups as deactivated. @@ -92,10 +105,10 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: store i1 false // WIN32: br i1 // True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true, i1* %[[arg1_cond]] // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true @@ -108,13 +121,13 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() // Two normal cleanups for TakeRef args. // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Somewhere in the landing pad soup, we conditionally destroy arg1. // WIN32: %[[isactive:.*]] = load i1* %[[arg1_cond]] // WIN32: br i1 %[[isactive]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: } namespace crash_on_partial_destroy { diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index c0dcd3cf83169..18e8c827eebe9 100755 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -1,7 +1,11 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify // FIXME: Test x86_64 member pointers when codegen no longer asserts on records // with virtual bases. +#ifndef INCOMPLETE_VIRTUAL struct B1 { void foo(); int b; @@ -56,20 +60,20 @@ int UnspecSingle::*us_d_memptr; // CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4 // CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4 // CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 } -// CHECK: { i32 0, i32 -1 }, align 4 +// CHECK: { i32 0, i32 -1 }, align 8 // CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 } -// CHECK: { i32 0, i32 -1 }, align 4 +// CHECK: { i32 0, i32 -1 }, align 8 // CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 } -// CHECK: { i32 0, i32 0, i32 -1 }, align 4 +// CHECK: { i32 0, i32 0, i32 -1 }, align 8 // CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 } -// CHECK: { i32 0, i32 0, i32 -1 }, align 4 +// CHECK: { i32 0, i32 0, i32 -1 }, align 8 void (Single ::*s_f_memptr)(); void (Multiple::*m_f_memptr)(); void (Virtual ::*v_f_memptr)(); // CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4 -// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4 -// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4 +// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 8 +// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 8 // We can define Unspecified after locking in the inheritance model. struct Unspecified : Multiple, Virtual { @@ -91,13 +95,13 @@ void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo; // CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" = // CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4 // CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" = -// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4 +// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 8 // CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" = -// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4 +// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 8 // CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" = -// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 4 +// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 8 // CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" = -// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4 +// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 8 } namespace CastParam { @@ -119,11 +123,11 @@ void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo; // Try a reinterpret_cast followed by a memptr conversion. void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo; // CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" = -// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4 +// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 8 void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0; // CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" = -// CHECK: global { i8*, i32 } zeroinitializer, align 4 +// CHECK: global { i8*, i32 } zeroinitializer, align 8 struct D : C { virtual void isPolymorphic(); @@ -156,23 +160,23 @@ void EmitNonVirtualMemberPointers() { void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo; // CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} { // CHECK: alloca i8*, align 4 -// CHECK: alloca { i8*, i32 }, align 4 -// CHECK: alloca { i8*, i32, i32 }, align 4 -// CHECK: alloca { i8*, i32, i32, i32 }, align 4 +// CHECK: alloca { i8*, i32 }, align 8 +// CHECK: alloca { i8*, i32, i32 }, align 8 +// CHECK: alloca { i8*, i32, i32, i32 }, align 8 // CHECK: store i8* bitcast (void (%{{.*}}*)* @"\01?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4 // CHECK: store { i8*, i32 } // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Multiple@@QAEXXZ" to i8*), i32 0 }, -// CHECK: { i8*, i32 }* %{{.*}}, align 4 +// CHECK: { i8*, i32 }* %{{.*}}, align 8 // CHECK: store { i8*, i32, i32 } // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, -// CHECK: { i8*, i32, i32 }* %{{.*}}, align 4 +// CHECK: { i8*, i32, i32 }* %{{.*}}, align 8 // CHECK: store { i8*, i32, i32, i32 } // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, -// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4 +// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 8 // CHECK: store { i8*, i32, i32, i32 } // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*), // CHECK: i32 0, i32 4, i32 0 }, -// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4 +// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 8 // CHECK: ret void // CHECK: } } @@ -219,27 +223,31 @@ void polymorphicMemPtrs() { bool nullTestDataUnspecified(int Unspecified::*mp) { return mp; // CHECK: define zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} { -// CHECK: %{{.*}} = load { i32, i32, i32 }* %{{.*}}, align 4 -// CHECK: store { i32, i32, i32 } {{.*}} align 4 -// CHECK: %[[mp:.*]] = load { i32, i32, i32 }* %{{.*}}, align 4 +// CHECK: %{{.*}} = load { i32, i32, i32 }* %{{.*}}, align 8 +// CHECK: store { i32, i32, i32 } {{.*}} align 8 +// CHECK: %[[mp:.*]] = load { i32, i32, i32 }* %{{.*}}, align 8 // CHECK: %[[mp0:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 0 // CHECK: %[[cmp0:.*]] = icmp ne i32 %[[mp0]], 0 // CHECK: %[[mp1:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 1 // CHECK: %[[cmp1:.*]] = icmp ne i32 %[[mp1]], 0 -// CHECK: %[[and0:.*]] = and i1 %[[cmp0]], %[[cmp1]] +// CHECK: %[[and0:.*]] = or i1 %[[cmp0]], %[[cmp1]] // CHECK: %[[mp2:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 2 // CHECK: %[[cmp2:.*]] = icmp ne i32 %[[mp2]], -1 -// CHECK: %[[and1:.*]] = and i1 %[[and0]], %[[cmp2]] +// CHECK: %[[and1:.*]] = or i1 %[[and0]], %[[cmp2]] // CHECK: ret i1 %[[and1]] // CHECK: } + +// Pass this large type indirectly. +// X64-LABEL: define zeroext i1 @"\01?nullTestDataUnspecified@@ +// X64: ({ i32, i32, i32 }*) } bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) { return mp; // CHECK: define zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} { -// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }* %{{.*}}, align 4 -// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 4 -// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }* %{{.*}}, align 4 +// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }* %{{.*}}, align 8 +// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 8 +// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }* %{{.*}}, align 8 // CHECK: %[[mp0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[mp]], 0 // CHECK: %[[cmp0:.*]] = icmp ne i8* %[[mp0]], null // CHECK: ret i1 %[[cmp0]] @@ -252,7 +260,7 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) { // data pointer. // CHECK: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} { // CHECK: %[[o:.*]] = load %{{.*}}** %{{.*}}, align 4 -// CHECK: %[[memptr:.*]] = load { i32, i32 }* %{{.*}}, align 4 +// CHECK: %[[memptr:.*]] = load { i32, i32 }* %{{.*}}, align 8 // CHECK: %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0 // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1 // CHECK: %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8* @@ -268,6 +276,11 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) { // CHECK: %[[v12:.*]] = load i32* %[[v11]] // CHECK: ret i32 %[[v12]] // CHECK: } + +// A two-field data memptr on x64 gets coerced to i64 and is passed in a +// register or memory. +// X64-LABEL: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z" +// X64: (%struct.Virtual* %o, i64 %memptr.coerce) } int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) { @@ -276,7 +289,7 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) { // data pointer. // CHECK: define i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} { // CHECK: %[[o:.*]] = load %{{.*}}** %{{.*}}, align 4 -// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }* %{{.*}}, align 4 +// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }* %{{.*}}, align 8 // CHECK: %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0 // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 1 // CHECK: %[[memptr2:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 2 @@ -309,6 +322,11 @@ void callMemberPointerSingle(Single *o, void (Single::*memptr)()) { // CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}}) // CHECK: ret void // CHECK: } + +// X64-LABEL: define void @"\01?callMemberPointerSingle@@ +// X64: (%struct.Single* %o, i8* %memptr) +// X64: bitcast i8* %{{[^ ]*}} to void (%struct.Single*)* +// X64: ret void } void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) { @@ -355,6 +373,9 @@ bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) { // CHECK-NOT: icmp // CHECK: ret i1 %[[r]] // CHECK: } + +// X64-LABEL: define zeroext i1 @"\01?compareSingleFunctionMemptr@@ +// X64: (i8* %{{[^,]*}}, i8* %{{[^)]*}}) } bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) { @@ -390,6 +411,9 @@ bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) { // CHECK: %{{.*}} = and i1 %[[bits_or_null]], %[[cmp0]] // CHECK: ret i1 %{{.*}} // CHECK: } + +// X64-LABEL: define zeroext i1 @"\01?unspecFuncMemptrEq@@ +// X64: ({ i8*, i32, i32, i32 }*, { i8*, i32, i32, i32 }*) } bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) { @@ -432,6 +456,9 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) { // CHECK: and i1 // CHECK: ret i1 // CHECK: } + +// X64-LABEL: define zeroext i1 @"\01?unspecDataMemptrEq@@ +// X64: ({ i32, i32, i32 }*, { i32, i32, i32 }*) } void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() { @@ -462,7 +489,7 @@ void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() { // // CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} { // CHECK: store -// CHECK: %[[src:.*]] = load { i8*, i32 }* %{{.*}}, align 4 +// CHECK: %[[src:.*]] = load { i8*, i32 }* %{{.*}}, align 8 // CHECK: extractvalue { i8*, i32 } %[[src]], 0 // CHECK: icmp ne i8* %{{.*}}, null // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} @@ -487,7 +514,7 @@ void (D::*convertCToD(void (C::*mp)()))() { return mp; // CHECK: define void @"\01?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} { // CHECK: store -// CHECK: load { i8*, i32, i32 }* %{{.*}}, align 4 +// CHECK: load { i8*, i32, i32 }* %{{.*}}, align 8 // CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0 // CHECK: icmp ne i8* %{{.*}}, null // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} @@ -537,3 +564,92 @@ int A::*reinterpret(int C::*mp) { } } + +namespace Test3 { +// Make sure we cast 'this' to i8* before using GEP. + +struct A { + int a; + int b; +}; + +int *load_data(A *a, int A::*mp) { + return &(a->*mp); +// CHECK-LABEL: define i32* @"\01?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} { +// CHECK: %[[a:.*]] = load %"struct.Test3::A"** %{{.*}}, align 4 +// CHECK: %[[mp:.*]] = load i32* %{{.*}}, align 4 +// CHECK: %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8* +// CHECK: getelementptr inbounds i8* %[[a_i8]], i32 %[[mp]] +// CHECK: } +} + +} + +namespace Test4 { + +struct A { virtual void f(); }; +struct B { virtual void g(); }; +struct C : A, B { virtual void g(); }; + +void (C::*getmp())() { + return &C::g; +} +// CHECK-LABEL: define i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"() +// CHECK: store { i8*, i32 } { i8* bitcast (void (i8*)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}} +// + +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(i8*) +// CHECK-NOT: getelementptr +// CHECK: load void (i8*)*** %{{.*}} +// CHECK: getelementptr inbounds void (i8*)** %{{.*}}, i64 0 +// CHECK-NOT: getelementptr +// CHECK: call x86_thiscallcc void % + +} + +namespace pr20007 { +struct A { + void f(); + void f(int); +}; +struct B : public A {}; +void test() { void (B::*a)() = &B::f; } +// CHECK-LABEL: define void @"\01?test@pr20007@@YAXXZ" +// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"\01?f@A@pr20007@@QAEXXZ" to i8*) +} + +namespace pr20007_kw { +struct A { + void f(); + void f(int); +}; +struct __single_inheritance B; +struct B : public A {}; +void test() { void (B::*a)() = &B::f; } +// CHECK-LABEL: define void @"\01?test@pr20007_kw@@YAXXZ" +// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*) +} + +namespace pr19987 { +template <typename T> +struct S { + int T::*x; +}; + +struct U : S<U> {}; + +static_assert(sizeof(S<U>::x) == 12, ""); +} + +#else +struct __virtual_inheritance A; +#ifdef MEMFUN +int foo(A *a, int (A::*mp)()) { + return (a->*mp)(); // expected-error{{requires a complete class type}} +} +#else +int foo(A *a, int A::*mp) { + return a->*mp; // expected-error{{requires a complete class type}} +} +#endif +#endif diff --git a/test/CodeGenCXX/microsoft-abi-methods.cpp b/test/CodeGenCXX/microsoft-abi-methods.cpp index c996ba5b8473e..579e549ab46c4 100644 --- a/test/CodeGenCXX/microsoft-abi-methods.cpp +++ b/test/CodeGenCXX/microsoft-abi-methods.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s class C { public: diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp index 802f0ca24175e..b1c1482eff6f5 100644 --- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s struct Left { virtual void left(); diff --git a/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp b/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp new file mode 100755 index 0000000000000..0c82ac328649c --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s + +struct C0 { int a; }; +struct C1 { int a; virtual void C1M() {} }; +struct C2 { int a; virtual void C2M() {} }; +struct C3 : C0, C1, C2 {} a; + +// Check to see that both C1 and C2 get laid out before C0 does. +// CHECK: %struct.C3 = type { %struct.C1, %struct.C2, %struct.C0 } diff --git a/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp new file mode 100644 index 0000000000000..d305dd83271f2 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -fno-rtti -emit-llvm-only -o - -triple=i386-pc-win32 -verify + +// A is not trivially copyable and must be passed indirectly or with inalloca. +struct A { + A(); + A(const A &o); + virtual ~A(); + int a; +}; + +struct B { + B(); + int b; + virtual B *clone(A); +}; + +// Converting from C* to B* requires a this adjustment. +struct C : A, B { + C(); + int c; + virtual C *clone(A); // expected-error {{cannot compile this non-trivial argument copy for thunk yet}} +}; +B::B() {} // force emission +C::C() {} // force emission diff --git a/test/CodeGenCXX/microsoft-abi-rtti.cpp b/test/CodeGenCXX/microsoft-abi-rtti.cpp new file mode 100644 index 0000000000000..062f597b37839 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-rtti.cpp @@ -0,0 +1,267 @@ +// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 2>/dev/null %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 2>/dev/null %s | FileCheck --check-prefix=X64 %s + +struct N {}; +struct M : private N {}; +struct X { virtual void f() {} }; +class Z { virtual void f() {} }; +class V : public X { virtual void f() {} }; +class W : M, virtual V { public: virtual void f() {} }; +class Y : Z, W, virtual V { public: virtual void g() {} } y; + +struct A {}; +struct B : A {}; +struct C : B { virtual void f() {} } c; + +struct X1 { virtual void f() {} }; +struct V1 : X1 {}; +struct W1 : virtual V1 {}; +struct Y1 : W1, virtual V1 {} y1; + +struct A1 { virtual void f() {} }; +struct B1 : virtual A1 { virtual void f() {} B1() {} } b1; + +struct Z2 { virtual void f() {} }; +struct Y2 { virtual void f() {} }; +struct A2 : Z2, Y2 {}; +struct B2 : virtual A2 { B2() {} virtual void f() {} } b2; + +// CHECK: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" } +// CHECK: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" } +// CHECK: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*]* @"\01??_R2B2@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" } +// CHECK: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" } +// CHECK: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" } +// CHECK: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2A2@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" } +// CHECK: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" } +// CHECK: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" } +// CHECK: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z2@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" } +// CHECK: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" } +// CHECK: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y2@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" } +// CHECK: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" } +// CHECK: @"\01??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" } +// CHECK: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" } +// CHECK: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" } +// CHECK: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" } +// CHECK: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" } +// CHECK: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" } +// CHECK: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" } +// CHECK: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" } +// CHECK: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" } +// CHECK: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" } +// CHECK: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" } +// CHECK: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" } +// CHECK: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" } +// CHECK: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" } +// CHECK: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" } +// CHECK: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" } +// CHECK: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" } +// CHECK: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" } +// CHECK: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2W1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" } +// CHECK: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" } +// CHECK: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" } +// CHECK: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" } +// CHECK: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" } +// CHECK: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X1@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" } +// CHECK: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" } +// CHECK: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" } +// CHECK: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" } +// CHECK: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" } +// CHECK: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" } +// CHECK: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2C@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" } +// CHECK: @"\01??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" } +// CHECK: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" } +// CHECK: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" } +// CHECK: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" } +// CHECK: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" } +// CHECK: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" } +// CHECK: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" } +// CHECK: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" } +// CHECK: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" } +// CHECK: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" } +// CHECK: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" } +// CHECK: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" } +// CHECK: @"\01??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" } +// CHECK: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" } +// CHECK: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*]* @"\01??_R2W@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" } +// CHECK: @"\01??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" } +// CHECK: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" } +// CHECK: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2M@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" } +// CHECK: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" } +// CHECK: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" } +// CHECK: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2N@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" } +// CHECK: @"\01??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" } +// CHECK: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" } +// CHECK: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" } +// CHECK: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" } +// CHECK: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" } +// CHECK: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" } +// CHECK: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X@@8", i32 0, i32 0) } +// CHECK: @"\01??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null] +// CHECK: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" } +// CHECK: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" } +// CHECK: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" } +// CHECK: @"\01??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" } +// CHECK: @"\01??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" } +// CHECK: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" } +// CHECK: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" } +// CHECK: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" } +// CHECK: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" } +// CHECK: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" } + +// X64: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" } +// X64: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"\01??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" } +// X64: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" } +// X64: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" } +// X64: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" } +// X64: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" } +// X64: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" } +// X64: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"\01??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" } +// X64: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" } +// X64: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" } +// X64: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" } +// X64: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" } +// X64: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" } +// X64: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" } +// X64: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"\01??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" } +// X64: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" } +// X64: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"\01??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" } +// X64: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" } +// X64: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" } +// X64: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" } +// X64: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0] +// X64: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } +// X64: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) } diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index d0750e6ebe914..96c23c66b8963 100644 --- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fno-rtti | FileCheck -check-prefix WIN64 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s struct Empty {}; @@ -47,6 +47,20 @@ struct Big { int a, b, c, d, e, f; }; +struct BigWithDtor { + BigWithDtor(); + ~BigWithDtor(); + int a, b, c, d, e, f; +}; + +// WIN32: declare void @"{{.*take_bools_and_chars.*}}" +// WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, +// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca) +void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g); +void call_bools_and_chars() { + take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false); +} + // Returning structs that fit into a register. Small small_return() { return Small(); } // LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result) @@ -103,18 +117,46 @@ void small_arg_with_ctor(SmallWithCtor s) {} // Test that dtors are invoked in the callee. void small_arg_with_dtor(SmallWithDtor s) {} -// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval align 4 %s) {{.*}} { -// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"(%struct.SmallWithDtor* %s) +// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} { +// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ" // WIN32: } -// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval %s) {{.*}} { -// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s) +// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} { +// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ" // WIN64: } +void call_small_arg_with_dtor() { + small_arg_with_dtor(SmallWithDtor()); +} +// The temporary is copied, so it's destroyed in the caller as well as the +// callee. +// WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"() +// WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ" +// WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}}) +// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ" +// WIN64: ret void + // Test that references aren't destroyed in the callee. void ref_small_arg_with_dtor(const SmallWithDtor &s) { } -// WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} { +// WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} { // WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ" // WIN32: } +// WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) + +void big_arg_with_dtor(BigWithDtor s) {} +// WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s) +// WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ" +// WIN64: } + +void call_big_arg_with_dtor() { + big_arg_with_dtor(BigWithDtor()); +} +// We can elide the copy of the temporary in the caller, because this object is +// larger than 8 bytes and is passed indirectly. +// WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"() +// WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ" +// WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}}) +// WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ" +// WIN64: ret void // Test that temporaries passed by reference are destroyed in the caller. void temporary_ref_with_dtor() { @@ -141,60 +183,65 @@ void eh_cleanup_arg_with_dtor() { void small_arg_with_vftable(SmallWithVftable s) {} // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s) -// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval align 4 %s) -// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval %s) +// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca) +// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s) void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {} // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s) -// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval align 4 %s) -// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval %s) +// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca) +// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) void big_arg(Big s) {} // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s) // WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s) // WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s) -// FIXME: Add WIN64 tests. Currently, even the method manglings are wrong (sic!). class Class { public: Small thiscall_method_small() { return Small(); } // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this) - // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this) + // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result) + // WIN64: define linkonce_odr void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result) SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); } // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this) - // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this) + // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result) + // WIN64: define linkonce_odr void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result) Small __cdecl cdecl_method_small() { return Small(); } // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this) - // FIXME: Interesting, cdecl returns structures differently for instance - // methods and global functions. This is not supported by Clang yet... - // FIXME: Replace WIN32-NOT with WIN32 when this is fixed. - // WIN32-NOT: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this) + // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result) + // WIN64: define linkonce_odr void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result) Big __cdecl cdecl_method_big() { return Big(); } // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this) - // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result, %class.Class* %this) + // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result) + // WIN64: define linkonce_odr void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result) void thiscall_method_arg(Empty s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this) // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s) + // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce) void thiscall_method_arg(EmptyWithCtor s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this) // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s) + // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce) void thiscall_method_arg(Small s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, %struct.Small* byval align 4 %s) // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, %struct.Small* byval align 4 %s) + // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce) void thiscall_method_arg(SmallWithCtor s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s) // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s) + // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce) void thiscall_method_arg(Big s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s) // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s) + // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s) }; void use_class() { @@ -218,8 +265,8 @@ struct X { }; void g(X) { } -// WIN32: define void @"\01?g@@YAXUX@@@Z"(%struct.X* byval align 4) {{.*}} { -// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* %0) +// WIN32: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} { +// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}}) // WIN32: } void f() { g(X()); @@ -227,3 +274,72 @@ void f() { // WIN32: define void @"\01?f@@YAXXZ"() {{.*}} { // WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ" // WIN32: } + + +namespace test2 { +// We used to crash on this due to the mixture of POD byval and non-trivial +// byval. + +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial &o); + ~NonTrivial(); + int a; +}; +struct POD { int b; }; + +int foo(NonTrivial a, POD b); +void bar() { + POD b; + b.b = 13; + int c = foo(NonTrivial(), b); +} +// WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} { +// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]] +// WIN32: getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 +// WIN32: call void @llvm.memcpy +// WIN32: getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 +// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ" +// WIN32: call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem) +// WIN32: ret void +// WIN32: } + +} + +namespace test3 { + +// Check that we padded the inalloca struct to a multiple of 4. +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial &o); + ~NonTrivial(); + int a; +}; +void foo(NonTrivial a, bool b) { } +// WIN32-LABEL: define void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca) + +} + +// We would crash here because the later definition of ForwardDeclare1 results +// in a different IR type for the value we want to store. However, the alloca's +// type will use the argument type selected by fn1. +struct ForwardDeclare1; + +typedef void (*FnPtr1)(ForwardDeclare1); +void fn1(FnPtr1 a, SmallWithDtor b) { } + +struct ForwardDeclare1 {}; + +void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); }; +// WIN32-LABEL: define void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z" +// WIN32: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0 +// WIN32: %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]* +// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]] +// WIN32: %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 +// WIN32: %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8* +// WIN32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[bc1]], i8* {{.*}}, i32 4, i32 4, i1 false) +// WIN32: %[[a2:[^ ]*]] = load void [[dst_ty]]* %[[a1]], align 4 +// WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 +// WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]* +// WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4 +// WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]]) diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp index c0b9722123573..5f74c54c1c452 100644 --- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp +++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp @@ -1,8 +1,9 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s -// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }] -// CHECK: [{ i32, void ()* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@YAXXZ" }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] +// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] +// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", +// CHECK: i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }] struct S { S(); @@ -11,21 +12,34 @@ struct S { S s; -// CHECK: define internal void @"\01??__Es@@YAXXZ"() [[NUW:#[0-9]+]] -// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ" +// CHECK: define internal void @"\01??__Es@@YAXXZ"() +// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ" // CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ") // CHECK: ret void -// CHECK: define internal void @"\01??__Fs@@YAXXZ"() [[NUW]] { +// CHECK: define internal void @"\01??__Fs@@YAXXZ"() // CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ" // CHECK: ret void +// These globals should use distinct guard variables, and not different bits of +// the same global. +__declspec(selectany) S selectany1; +__declspec(selectany) S selectany2; +// CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"() +// CHECK-NOT: @"\01??_Bselectany1 +// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ" +// CHECK: ret void +// CHECK: define linkonce_odr void @"\01??__Eselectany2@@YAXXZ"() +// CHECK-NOT: @"\01??_Bselectany2 +// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ" +// CHECK: ret void + void StaticLocal() { static S TheS; } // CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"() -// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA" -// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA" +// CHECK: load i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA" +// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA" // CHECK: ret void MultipleStatics() { @@ -66,7 +80,7 @@ void MultipleStatics() { static S S35; } // CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"() -// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA" +// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4 @@ -74,7 +88,7 @@ void MultipleStatics() { // CHECK: and i32 {{.*}}, 16 // ... // CHECK: and i32 {{.*}}, -2147483648 -// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1" +// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA1" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4 @@ -85,6 +99,7 @@ class A { public: A() {} ~A() {} + int a; }; template<typename T> @@ -104,7 +119,7 @@ inline S &UnreachableStatic() { return s; } -// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"() +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"() // CHECK: and i32 {{.*}}, 2 // CHECK: or i32 {{.*}}, 2 // CHECK: ret @@ -114,7 +129,7 @@ inline S &getS() { return TheS; } -// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?getS@@YAAAUS@@XZ" +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ" // CHECK: load i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51" // CHECK: and i32 {{.*}}, 1 // CHECK: icmp ne i32 {{.*}}, 0 @@ -128,27 +143,95 @@ inline S &getS() { // init.end: // CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A" +inline int enum_in_function() { + // CHECK-LABEL: define linkonce_odr i32 @"\01?enum_in_function@@YAHXZ"() + static enum e { foo, bar, baz } x; + // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A" + static int y; + // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA" + return x + y; +}; + +struct T { + enum e { foo, bar, baz }; + int enum_in_struct() { + // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ" + static int x; + // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA" + return x++; + } +}; + +inline int switch_test(int x) { + // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test@@YAHH@Z"(i32 %x) + switch (x) { + static int a; + // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA" + case 0: + a++; + return 1; + case 1: + static int b; + // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA" + return b++; + case 2: { + static int c; + // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA" + return b + c++; + } + }; +} + +int f(); +inline void switch_test2() { + // CHECK-LABEL: define linkonce_odr void @"\01?switch_test2@@YAXXZ"() + // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA" + switch (1) default: static int x = f(); +} + +namespace DynamicDLLImportInitVSMangling { + // Failing to pop the ExprEvalContexts when instantiating a dllimport var with + // dynamic initializer would cause subsequent static local numberings to be + // incorrect. + struct NonPOD { NonPOD(); }; + template <typename T> struct A { static NonPOD x; }; + template <typename T> NonPOD A<T>::x; + template struct __declspec(dllimport) A<int>; + + inline int switch_test3() { + // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ" + static int local; + // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA" + return local++; + } +} + void force_usage() { UnreachableStatic(); getS(); (void)B<int>::foo; // (void) - force usage + enum_in_function(); + (void)&T::enum_in_struct; + switch_test(1); + switch_test2(); + DynamicDLLImportInitVSMangling::switch_test3(); } -// CHECK: define internal void @"\01??__Efoo@?$B@H@@YAXXZ"() [[NUW]] -// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ" -// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@YAXXZ") +// CHECK: define linkonce_odr void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"() +// CHECK-NOT: and +// CHECK-NOT: ?_Bfoo@ +// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ" +// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ") // CHECK: ret void // CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ" // CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ" -// CHECK: define internal void @"\01??__Ffoo@?$B@H@@YAXXZ" +// CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ" // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo // CHECK: ret void -// CHECK: define internal void @_GLOBAL__I_a() [[NUW]] { +// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp() // CHECK: call void @"\01??__Es@@YAXXZ"() // CHECK: ret void - -// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp index d54520fab72c3..f977556aa5650 100644 --- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp @@ -1,9 +1,26 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s namespace test1 { template <typename T> class A { ~A() {} }; template class A<char>; -// CHECK: define weak_odr x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ" +// CHECK-DAG: define weak_odr x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ" +} + +namespace test2 { +struct A { + virtual ~A(); +}; +struct B : A { + B(); + virtual ~B(); +}; + +A::~A() {} +B::~B() {} +void foo() { + B b; +} +// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*) } diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index c2f1395f47dfb..7d3992b9940bf 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -1,10 +1,12 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t +// RUN: %clang_cc1 -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t // RUN: FileCheck %s < %t // vftables are emitted very late, so do another pass to try to keep the checks // in source order. // RUN: FileCheck --check-prefix DTORS %s < %t +// RUN: FileCheck --check-prefix DTORS2 %s < %t +// RUN: FileCheck --check-prefix DTORS3 %s < %t // -// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s namespace basic { @@ -121,6 +123,79 @@ void use_D() { D c; } } // end namespace basic +namespace dtor_in_second_nvbase { + +struct A { + virtual void f(); // A needs vftable to be primary. +}; +struct B { + virtual ~B(); +}; +struct C : A, B { + virtual ~C(); +}; + +C::~C() { +// CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ" +// CHECK: (%"struct.dtor_in_second_nvbase::C"* %this) +// No this adjustment! +// CHECK-NOT: getelementptr +// CHECK: load %"struct.dtor_in_second_nvbase::C"** %{{.*}} +// Now we this-adjust before calling ~B. +// CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8* +// CHECK: getelementptr inbounds i8* %{{.*}}, i64 4 +// CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"* +// CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ" +// CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}}) +// CHECK: ret void +} + +void foo() { + C c; +} +// DTORS2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" +// DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete) +// Do an adjustment from B* to C*. +// DTORS2: getelementptr i8* %{{.*}}, i32 -4 +// DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"* +// DTORS2: call x86_thiscallcc void @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" +// DTORS2: ret void + +} + +namespace test2 { +// Just like dtor_in_second_nvbase, except put that in a vbase of a diamond. + +// C's dtor is in the non-primary base. +struct A { virtual void f(); }; +struct B { virtual ~B(); }; +struct C : A, B { virtual ~C(); int c; }; + +// Diamond hierarchy, with C as the shared vbase. +struct D : virtual C { int d; }; +struct E : virtual C { int e; }; +struct F : D, E { ~F(); int f; }; + +F::~F() { +// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*) +// Do an adjustment from C vbase subobject to F as though F was the +// complete type. +// CHECK: getelementptr inbounds i8* %{{.*}}, i32 -20 +// CHECK: bitcast i8* %{{.*}} to %"struct.test2::F"* +// CHECK: store %"struct.test2::F"* +} + +void foo() { + F f; +} +// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ" +// Do an adjustment from C* to F*. +// DTORS3: getelementptr i8* %{{.*}}, i32 20 +// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"* +// DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ" +// DTORS3: ret void + +} namespace constructors { @@ -299,3 +374,69 @@ void call_nv_deleting_dtor(D *d) { } } + +namespace test1 { +struct A { }; +struct B : virtual A { + B(int *a); + B(const char *a, ...); + __cdecl B(short *a); +}; +B::B(int *a) {} +B::B(const char *a, ...) {} +B::B(short *a) {} +// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z" +// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived) +// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ" +// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...) + +// FIXME: This should be x86_thiscallcc. MSVC ignores explicit CCs on structors. +// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z" +// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived) + +void construct_b() { + int a; + B b1(&a); + B b2("%d %d", 1, 2); +} +// CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"() +// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z" +// CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1) +// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...)* @"\01??0B@test1@@QAA@PBDZZ" +// CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2) +} + +namespace implicit_copy_vtable { +// This was a crash that only reproduced in ABIs without key functions. +struct ImplicitCopy { + // implicit copy ctor + virtual ~ImplicitCopy(); +}; +void CreateCopy(ImplicitCopy *a) { + new ImplicitCopy(*a); +} +// CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@" + +struct MoveOnly { + MoveOnly(MoveOnly &&o) = default; + virtual ~MoveOnly(); +}; +MoveOnly &&f(); +void g() { new MoveOnly(f()); } +// CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@" +} + +// Dtor thunks for classes in anonymous namespaces should be internal, not +// linkonce_odr. +namespace { +struct A { + virtual ~A() { } +}; +} +void *getA() { + return (void*)new A(); +} +// CHECK: define internal x86_thiscallcc void @"\01??_GA@?A@@UAEPAXI@Z" +// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete) +// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ" +// CHECK: (%"struct.(anonymous namespace)::A"* %this) diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp index f1bc385fdff29..c755b300067d3 100644 --- a/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1 +// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1 // RUN: FileCheck --check-prefix=MANGLING %s < %t // RUN: FileCheck --check-prefix=XMANGLING %s < %t // RUN: FileCheck --check-prefix=CODEGEN %s < %t -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s +// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s void foo(void *); @@ -61,13 +61,13 @@ struct C : A, B { C::C() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) +// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) // CODEGEN: getelementptr i8* {{.*}}, i32 -4 // FIXME: should actually call _EC, not _GC. // CODEGEN: call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z" // CODEGEN: ret -// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* +// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* // CODEGEN: getelementptr i8* {{.*}}, i32 -4 // CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C* // CODEGEN: ret @@ -91,7 +91,7 @@ struct E : D { E::E() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ" +// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ" // CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ" // CODEGEN: getelementptr inbounds i8* {{.*}}, i32 4 // CODEGEN: ret @@ -124,7 +124,7 @@ struct I : D { I::I() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ" +// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ" // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ" // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8* // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4 @@ -152,3 +152,14 @@ struct C : A, B { }; C c; } + +namespace { +struct E : D { + E(); + virtual C* goo(); +}; +E::E() {} +E e; +// Class with internal linkage has internal linkage thunks. +// CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ" +} diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp new file mode 100644 index 0000000000000..95c2cbd817b39 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTRY +// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTHROW + +void external(); + +inline void not_emitted() { + throw int(13); // no error +} + +int main() { + int rv = 0; +#ifdef TRY + try { // expected-error {{cannot compile this try statement yet}} + external(); + } catch (int) { + rv = 1; + } +#endif +#ifdef THROW + throw int(42); // expected-error {{cannot compile this throw expression yet}} +#endif + return rv; +} diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp new file mode 100644 index 0000000000000..4ee004d51d215 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s + +struct type_info; +namespace std { using ::type_info; } + +struct V { virtual void f(); }; +struct A : virtual V { A(); }; + +extern A a; +extern V v; +extern int b; +A* fn(); + +const std::type_info* test0_typeid() { return &typeid(int); } +// CHECK-LABEL: define %struct.type_info* @"\01?test0_typeid@@YAPBUtype_info@@XZ"() +// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*) + +const std::type_info* test1_typeid() { return &typeid(A); } +// CHECK-LABEL: define %struct.type_info* @"\01?test1_typeid@@YAPBUtype_info@@XZ"() +// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to %struct.type_info*) + +const std::type_info* test2_typeid() { return &typeid(&a); } +// CHECK-LABEL: define %struct.type_info* @"\01?test2_typeid@@YAPBUtype_info@@XZ"() +// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0PAUA@@@8" to %struct.type_info*) + +const std::type_info* test3_typeid() { return &typeid(*fn()); } +// CHECK-LABEL: define %struct.type_info* @"\01?test3_typeid@@YAPBUtype_info@@XZ"() +// CHECK: [[CALL:%.*]] = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"() +// CHECK-NEXT: [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null +// CHECK-NEXT: br i1 [[CMP]] +// CHECK: tail call i8* @__RTtypeid(i8* null) +// CHECK-NEXT: unreachable +// CHECK: [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8* +// CHECK-NEXT: [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8** +// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4 +// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 +// CHECK-NEXT: [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32* +// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4 +// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]], i32 [[VBASE_OFFS]] +// CHECK-NEXT: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]]) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info* +// CHECK-NEXT: ret %struct.type_info* [[RET]] + +const std::type_info* test4_typeid() { return &typeid(b); } +// CHECK: define %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@@XZ"() +// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*) + +const std::type_info* test5_typeid() { return &typeid(v); } +// CHECK: define %struct.type_info* @"\01?test5_typeid@@YAPBUtype_info@@XZ"() +// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"\01?v@@3UV@@A" to i8*)) +// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info* +// CHECK-NEXT: ret %struct.type_info* [[RET]] diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp index 6de556b1d8147..8b86d6bd3c8e9 100644 --- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s // See microsoft-abi-structors.cpp for constructor codegen tests. @@ -477,3 +477,54 @@ F f; // CHECK-DAG: @"\01??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20] // CHECK-DAG: @"\01??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28] } + +namespace Test27 { +// PR17748 +struct A {}; +struct B : virtual A {}; +struct C : virtual B {}; +struct D : C, B {}; +struct E : D {}; +struct F : C, E {}; +struct G : F, D, C, B {}; +G x; + +// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@F@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@D@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@E@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@F@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BD@1@@" = +// CHECK-DAG: @"\01??_8G@Test27@@7BF@1@@" = +} + +namespace Test28 { +// PR17748 +struct A {}; +struct B : virtual A {}; +struct C : virtual B {}; +struct D : C, B {}; +struct E : C, D {}; +struct F : virtual E, virtual D, virtual C {}; +F x; + +// CHECK-DAG: @"\01??_8F@Test28@@7B01@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BB@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@E@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@E@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BD@1@@" = +// CHECK-DAG: @"\01??_8F@Test28@@7BE@1@@" = +} + +namespace Test29 { +struct A {}; +struct B : virtual A {}; +struct C : virtual B {}; +struct D : C {}; +D d; + +// CHECK-DAG: @"\01??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer +} diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp new file mode 100644 index 0000000000000..825aba010f125 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=NO-RTTI +// RUN: %clang_cc1 %s -triple=i386-pc-win32 -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=RTTI + +// RTTI-DAG: $"\01??_7S@@6B@" = comdat largest +// RTTI-DAG: $"\01??_7V@@6B@" = comdat largest +// RTTI-DAG: $"\01??_7W@?A@@6B@" = comdat largest + +struct S { + virtual ~S(); +} s; + +// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat $"\01??_7S@@6B@" +// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_S]], i32 0, i32 1) + +// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] + +struct __declspec(dllimport) U { + virtual ~U(); +} u; + +// RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] + +// NO-RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] + +struct __declspec(dllexport) V { + virtual ~V(); +} v; + +// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat $"\01??_7V@@6B@" +// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_V]], i32 0, i32 1) + +// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] + +namespace { +struct W { + virtual ~W(); +} w; +} +// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)], comdat $"\01??_7W@?A@@6B@" +// RTTI-DAG: @"\01??_7W@?A@@6B@" = unnamed_addr alias internal getelementptr inbounds ([2 x i8*]* @1, i32 0, i32 1) + +// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index 8e23ade658c4f..a6fcdea749abc 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s // For now, just make sure x86_64 doesn't crash. -// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t +// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t struct A { virtual void f(); @@ -23,7 +23,7 @@ struct D : virtual C { D::D() {} // Forces vftable emission. -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4 @@ -34,7 +34,7 @@ D::D() {} // Forces vftable emission. // CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]]) // CHECK: ret void -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -8 @@ -63,7 +63,7 @@ struct G : virtual F, virtual E { G::G() {} // Forces vftable emission. -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) // CHECK: %[[ECX:.*]] = load %struct.E** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4 diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 7c223ca0a7723..2f0fffee696f9 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 -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t +// RUN: %clang_cc1 %s -fno-rtti -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 -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t +// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t struct VBase { virtual ~VBase(); @@ -312,3 +312,151 @@ D::~D() { } } + +namespace test2 { +struct A { A(); }; +struct B : virtual A { B() {} }; +struct C : B, A { C() {} }; + +// PR18435: Order mattered here. We were generating code for the delegating +// call to B() from C(). +void callC() { C x; } + +// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @"\01??0C@test2@@QAE@XZ" +// CHECK: (%"struct.test2::C"* returned %this, i32 %is_most_derived) +// CHECK: br i1 +// Virtual bases +// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) +// CHECK: br label +// Non-virtual bases +// CHECK: call x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0) +// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) +// CHECK: ret + +// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ" +// CHECK2: (%"struct.test2::B"* returned %this, i32 %is_most_derived) +// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) +// CHECK2: ret + +} + +namespace test3 { +// PR19104: A non-virtual call of a virtual method doesn't use vftable thunks, +// so requires only static adjustment which is different to the one used +// for virtual calls. +struct A { + virtual void foo(); +}; + +struct B : virtual A { + virtual void bar(); +}; + +struct C : virtual A { + virtual void foo(); +}; + +struct D : B, C { + virtual void bar(); + int field; // Laid out between C and A subobjects in D. +}; + +void D::bar() { + // CHECK-LABEL: define x86_thiscallcc void @"\01?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this) + + C::foo(); + // Shouldn't need any vbtable lookups. All we have to do is adjust to C*, + // then compensate for the adjustment performed in the C::foo() prologue. + // CHECK-NOT: load i8** + // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8* + // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 8 + // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"* + // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8* + // CHECK: %[[ARG:.*]] = getelementptr i8* %[[C_i8]], i32 4 + // CHECK: call x86_thiscallcc void @"\01?foo@C@test3@@UAEXXZ"(i8* %[[ARG]]) + // CHECK: ret +} +} + +namespace test4{ +// PR19172: We used to merge method vftable locations wrong. + +struct A { + virtual ~A() {} +}; + +struct B { + virtual ~B() {} +}; + +struct C : virtual A, B { + virtual ~C(); +}; + +void foo(void*); + +C::~C() { + // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this) + + // In this case "this" points to the most derived class, so no GEPs needed. + // CHECK-NOT: getelementptr + // CHECK-NOT: bitcast + // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7C@test4@@6BB@1@@", [1 x i8*]** %[[VFPTR_i8]] + + foo(this); + // CHECK: ret +} + +void destroy(C *obj) { + // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj) + + delete obj; + // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)*** + // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]] + // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0 + // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]] + // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1) + // CHECK: ret +} + +struct D { + virtual void d(); +}; + +// The first non-virtual base doesn't have a vdtor, +// but "this adjustment" is not needed. +struct E : D, B, virtual A { + virtual ~E(); +}; + +E::~E() { + // CHECK-LABEL: define x86_thiscallcc void @"\01??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this) + + // In this case "this" points to the most derived class, so no GEPs needed. + // CHECK-NOT: getelementptr + // CHECK-NOT: bitcast + // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]** + // CHECK: store [1 x i8*]* @"\01??_7E@test4@@6BD@1@@", [1 x i8*]** %[[VFPTR_i8]] + foo(this); +} + +void destroy(E *obj) { + // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj) + + // CHECK-NOT: getelementptr + // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8* + // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4 + // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)*** + // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]] + // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0 + // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]] + // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8* + // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4 + // FIXME: in fact, the call should take i8* and the bitcast is redundant. + // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"* + // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1) + delete obj; +} + +} diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp index 51a04c89dcb7b..974953c014442 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp @@ -1,14 +1,23 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32 -// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64 +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32 +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64 struct S { int x, y, z; }; +// U is not trivially copyable, and requires inalloca to pass by value. +struct U { + int u; + U(); + ~U(); + U(const U &); +}; + struct C { virtual void foo(); virtual int bar(int, double); virtual S baz(int); + virtual S qux(U); }; namespace { @@ -31,18 +40,22 @@ void f() { void (D::*ptr4)(); ptr4 = &D::foo; + S (C::*ptr5)(U); + ptr5 = &C::qux; + + // CHECK32-LABEL: define void @"\01?f@@YAXXZ"() // CHECK32: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr // CHECK32: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2 -// CHECK32: store i8* bitcast (void (%struct.S*, %struct.C*, i32)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3 -// CHECK32: store i8* bitcast (void (%"struct.<anonymous namespace>::D"*)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4 +// CHECK32: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3 +// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4 // CHECK32: } // // CHECK64-LABEL: define void @"\01?f@@YAXXZ"() // CHECK64: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr // CHECK64: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2 -// CHECK64: store i8* bitcast (void (%struct.S*, %struct.C*, i32)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3 -// CHECK64: store i8* bitcast (void (%"struct.<anonymous namespace>::D"*)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr +// CHECK64: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3 +// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr // CHECK64: } } @@ -51,14 +64,14 @@ void f() { // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this) unnamed_addr // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0 // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]] -// CHECK32: call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}) +// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}) // CHECK32: ret void // CHECK32: } // // CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this) unnamed_addr // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0 // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]] -// CHECK64: call void [[CALLEE]](%struct.C* %{{.*}}) +// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}) // CHECK64: ret void // CHECK64: } @@ -66,43 +79,58 @@ void f() { // CHECK32-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01??_9C@@$B3AE"(%struct.C* %this, i32, double) unnamed_addr // CHECK32: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1 // CHECK32: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]] -// CHECK32: [[CALL:%.*]] = call x86_thiscallcc i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) +// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) // CHECK32: ret i32 [[CALL]] // CHECK32: } // // CHECK64-LABEL: define linkonce_odr i32 @"\01??_9C@@$B7AA"(%struct.C* %this, i32, double) unnamed_addr // CHECK64: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1 // CHECK64: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]] -// CHECK64: [[CALL:%.*]] = call i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) +// CHECK64: [[CALL:%.*]] = musttail call i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) // CHECK64: ret i32 [[CALL]] // CHECK64: } // Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct. -// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.S* noalias sret %agg.result, %struct.C* %this, i32) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.S*, %struct.C*, i32)** %{{.*}}, i64 2 -// CHECK32: [[CALLEE:%.*]] = load void (%struct.S*, %struct.C*, i32)** [[VPTR]] -// CHECK32: call x86_thiscallcc void [[CALLEE]](%struct.S* sret %agg.result, %struct.C* %{{.*}}, i32 %{{.*}}) +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}}) // CHECK32: ret void // CHECK32: } // -// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.S* noalias sret %agg.result, %struct.C* %this, i32) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.S*, %struct.C*, i32)** %{{.*}}, i64 2 -// CHECK64: [[CALLEE:%.*]] = load void (%struct.S*, %struct.C*, i32)** [[VPTR]] -// CHECK64: call void [[CALLEE]](%struct.S* sret %agg.result, %struct.C* %{{.*}}, i32 %{{.*}}) +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]] +// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}}) // CHECK64: ret void // CHECK64: } // Thunk for calling the virtual function in internal class D. -// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.<anonymous namespace>::D"* %this) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.<anonymous namespace>::D"*)** %{{.*}}, i64 0 -// CHECK32: [[CALLEE:%.*]] = load void (%"struct.<anonymous namespace>::D"*)** [[VPTR]] -// CHECK32: call x86_thiscallcc void [[CALLEE]](%"struct.<anonymous namespace>::D"* %{{.*}}) +// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0 +// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}) // CHECK32: ret void // CHECK32: } // -// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.<anonymous namespace>::D"* %this) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.<anonymous namespace>::D"*)** %{{.*}}, i64 0 -// CHECK64: [[CALLEE:%.*]] = load void (%"struct.<anonymous namespace>::D"*)** [[VPTR]] -// CHECK64: call void [[CALLEE]](%"struct.<anonymous namespace>::D"* %{{.*}}) +// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0 +// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]] +// CHECK64: musttail call void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}) +// CHECK64: ret void +// CHECK64: } + +// Thunk for calling the fourth virtual function in C, taking a struct parameter and returning a struct. +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc %struct.S* @"\01??_9C@@$BM@AE"(%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca) unnamed_addr +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** %{{.*}}, i64 3 +// CHECK32: [[CALLEE:%.*]] = load %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** [[VPTR]] +// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc %struct.S* [[CALLEE]](%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca %{{.*}}) +// CHECK32: ret %struct.S* [[CALL]] +// CHECK32: } +// +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.U*) unnamed_addr +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, %struct.U*)** %{{.*}}, i64 3 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, %struct.U*)** [[VPTR]] +// CHECK64: musttail call void [[CALLEE]](%struct.C* %this, %struct.S* sret %agg.result, %struct.U* %{{.*}}) // CHECK64: ret void // CHECK64: } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp new file mode 100644 index 0000000000000..86314cff324e3 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp @@ -0,0 +1,302 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t +// RUN: FileCheck %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll + +namespace test1 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + // Add an extra virtual method so it's easier to check for the absence of thunks. + virtual void h(); +}; + +struct X : A, B { + // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (1 entry) + // CHECK-NEXT: 0 | void test1::X::f() + + // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (2 entries) + // CHECK-NEXT: 0 | void test1::B::g() + // CHECK-NEXT: 1 | void test1::B::h() + + // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry) + // CHECK-NEXT: 0 | void test1::X::f() + + // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@" + // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@" + + // Overrides only the left child's method (A::f), needs no thunks. + virtual void f(); +} x; + +void build_vftable(X *obj) { obj->f(); } +} + +namespace test2 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct X : A, B { + // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry) + // CHECK-NEXT: 0 | void test2::A::f() + + // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries) + // CHECK-NEXT: 0 | void test2::X::g() + // CHECK-NEXT: 1 | void test2::B::h() + + // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void test2::X::g() + + // Overrides only the right child's method (B::g), needs this adjustment but + // not thunks. + virtual void g(); +}; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace test3 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct X : A, B { + // CHECK-LABEL: VFTable for 'test3::A' in 'test3::X' (2 entries) + // CHECK-NEXT: 0 | void test3::A::f() + // CHECK-NEXT: 1 | void test3::X::i() + + // CHECK-LABEL: VFTable for 'test3::B' in 'test3::X' (2 entries) + // CHECK-NEXT: 0 | void test3::B::g() + // CHECK-NEXT: 1 | void test3::B::h() + + // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry). + // CHECK-NEXT: 1 | void test3::X::i() + + // Only adds a new method. + virtual void i(); +}; + +void build_vftable(X *obj) { obj->i(); } +} + +namespace test4 { +struct A { + virtual void f(); +}; + +struct Empty { }; // Doesn't have a vftable! + +// Only the right base has a vftable, so it's laid out before the left one! +struct X : Empty, A { + // CHECK-LABEL: VFTable for 'test4::A' in 'test4::X' (1 entry) + // CHECK-NEXT: 0 | void test4::X::f() + + // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry). + // CHECK-NEXT: 0 | void test4::X::f() + + // MANGLING-DAG: @"\01??_7X@test4@@6B@" + + virtual void f(); +} x; + +void build_vftable(X *obj) { obj->f(); } +} + +namespace test5 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C : A, B { + virtual void f(); +}; + +struct X : C { + // CHECK-LABEL: VFTable for 'test5::A' in 'test5::C' in 'test5::X' (1 entry). + // CHECK-NEXT: 0 | void test5::X::f() + + // CHECK-LABEL: VFTable for 'test5::B' in 'test5::C' in 'test5::X' (2 entries). + // CHECK-NEXT: 0 | void test5::B::g() + // CHECK-NEXT: 1 | void test5::B::h() + + // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry). + // CHECK-NEXT: 0 | void test5::X::f() + + // MANGLING-DAG: @"\01??_7X@test5@@6BA@1@@" + // MANGLING-DAG: @"\01??_7X@test5@@6BB@1@@" + + // Overrides both C::f and A::f. + virtual void f(); +} x; + +void build_vftable(X *obj) { obj->f(); } +} + +namespace test6 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct X : C { + // CHECK-LABEL: VFTable for 'test6::A' in 'test6::C' in 'test6::X' (1 entry). + // CHECK-NEXT: 0 | void test6::A::f() + + // CHECK-LABEL: VFTable for 'test6::B' in 'test6::C' in 'test6::X' (2 entries). + // CHECK-NEXT: 0 | void test6::X::g() + // CHECK-NEXT: 1 | void test6::B::h() + + // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void test6::X::g() + + // Overrides both C::g and B::g. + virtual void g(); +}; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace test7 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C : A, B { + // Only adds a new method. + virtual void i(); +}; + +struct X : C { + // CHECK-LABEL: VFTable for 'test7::A' in 'test7::C' in 'test7::X' (2 entries). + // CHECK-NEXT: 0 | void test7::A::f() + // CHECK-NEXT: 1 | void test7::C::i() + + // CHECK-LABEL: VFTable for 'test7::B' in 'test7::C' in 'test7::X' (2 entries). + // CHECK-NEXT: 0 | void test7::X::g() + // CHECK-NEXT: 1 | void test7::B::h() + + // CHECK-LABEL: VFTable indices for 'test7::X' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void test7::X::g() + + // Overrides grandparent's B::g. + virtual void g(); +}; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace test8 { +struct A { + virtual void f(); +}; + +struct B : A { + virtual void g(); +}; + +// There are two 'A' subobjects in this class. +struct X : A, B { + // CHECK-LABEL: VFTable for 'test8::A' in 'test8::X' (2 entries). + // CHECK-NEXT: 0 | void test8::A::f() + // CHECK-NEXT: 1 | void test8::X::h() + + // CHECK-LABEL: VFTable for 'test8::A' in 'test8::B' in 'test8::X' (2 entries). + // CHECK-NEXT: 0 | void test8::A::f() + // CHECK-NEXT: 1 | void test8::B::g() + + // CHECK-LABEL: VFTable indices for 'test8::X' (1 entry). + // CHECK-NEXT: 1 | void test8::X::h() + + // MANGLING-DAG: @"\01??_7X@test8@@6BA@1@@" + // MANGLING-DAG: @"\01??_7X@test8@@6BB@1@@" + + virtual void h(); +} x; + +void build_vftable(X *obj) { obj->h(); } +} + +namespace test9 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C : A, B { + // Overrides only the left child's method (A::f). + virtual void f(); +}; + +struct D : A, B { + // Overrides only the right child's method (B::g). + virtual void g(); +}; + +// 2-level structure with repeating subobject types, but no thunks needed. +struct X : C, D { + // CHECK-LABEL: VFTable for 'test9::A' in 'test9::C' in 'test9::X' (2 entries) + // CHECK-NEXT: 0 | void test9::C::f() + // CHECK-NEXT: 1 | void test9::X::z() + + // CHECK-LABEL: VFTable for 'test9::B' in 'test9::C' in 'test9::X' (2 entries) + // CHECK-NEXT: 0 | void test9::B::g() + // CHECK-NEXT: 1 | void test9::B::h() + + // CHECK-LABEL: VFTable for 'test9::A' in 'test9::D' in 'test9::X' (1 entry) + // CHECK-NEXT: 0 | void test9::A::f() + + // CHECK-LABEL: VFTable for 'test9::B' in 'test9::D' in 'test9::X' (2 entries) + // CHECK-NEXT: 0 | void test9::D::g() + // CHECK-NEXT: 1 | void test9::B::h() + + // CHECK-LABEL: VFTable indices for 'test9::X' (1 entry). + // CHECK-NEXT: 1 | void test9::X::z() + + // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@C@1@@" + // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@D@1@@" + // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@C@1@@" + // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@D@1@@" + + virtual void z(); +} x; + +void build_vftable(test9::X *obj) { obj->z(); } +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp new file mode 100644 index 0000000000000..76182a2e331e1 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t +// RUN: FileCheck %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll + +struct A { + virtual void f(); +}; + +struct B { + virtual void g() = 0; + virtual void h(); +}; + +struct C : A, B { + // CHECK-LABEL: VFTable for 'A' in 'C' (1 entry) + // CHECK-NEXT: 0 | void A::f() + + // CHECK-LABEL: VFTable for 'B' in 'C' (2 entries) + // CHECK-NEXT: 0 | void C::g() + // CHECK-NEXT: 1 | void B::h() + + // CHECK-LABEL: VFTable indices for 'C' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void C::g() + + // MANGLING-DAG: @"\01??_7C@@6BA@@@" + // MANGLING-DAG: @"\01??_7C@@6BB@@@" + + // Overrides only the right child's method (B::g), + // needs this adjustment but not thunks. + virtual void g(); +}; + +C c; +void build_vftable(C *obj) { obj->g(); } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp new file mode 100644 index 0000000000000..2d0bf63622963 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp @@ -0,0 +1,297 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t +// RUN: FileCheck %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll + +namespace test1 { +struct A { + virtual void g(); + // Add an extra virtual method so it's easier to check for the absence of thunks. + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +// Overrides a method of two bases at the same time, thus needing thunks. +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct X : D { + // CHECK-LABEL: VFTable for 'test1::D' in 'test1::X' (3 entries). + // CHECK-NEXT: 0 | test1::C *test1::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual] + // CHECK-NEXT: 1 | void test1::D::z() + // CHECK-NEXT: 2 | test1::C *test1::X::foo() + + // CHECK-LABEL: Thunks for 'test1::C *test1::X::foo()' (1 entry). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test1::B *'): 4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry). + // CHECK-NEXT: 2 | test1::C *test1::X::foo() + + // MANGLING-DAG: @"\01??_7X@test1@@6B@" + + virtual C* foo(); +} x; + +void build_vftable(X *obj) { obj->foo(); } +} + +namespace test2 { +struct A { + virtual void g(); + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct E : D { + virtual C* foo(); +}; + +struct F : C { }; + +struct X : E { + virtual F* foo(); + // CHECK-LABEL: VFTable for 'test2::D' in 'test2::E' in 'test2::X' (4 entries). + // CHECK-NEXT: 0 | test2::F *test2::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual] + // CHECK-NEXT: 1 | void test2::D::z() + // CHECK-NEXT: 2 | test2::F *test2::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test2::C *'): 0 non-virtual] + // CHECK-NEXT: 3 | test2::F *test2::X::foo() + + // CHECK-LABEL: Thunks for 'test2::F *test2::X::foo()' (2 entries). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test2::C *'): 0 non-virtual] + // CHECK-NEXT: 1 | [return adjustment (to type 'struct test2::B *'): 4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry). + // CHECK-NEXT: 3 | test2::F *test2::X::foo() +}; + +void build_vftable(X *obj) { obj->foo(); } +} + +namespace test3 { +struct A { + virtual void g(); + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct E : D { + virtual C* foo(); +}; + +struct F : A, C { }; + +struct X : E { + // CHECK-LABEL: VFTable for 'test3::D' in 'test3::E' in 'test3::X' (4 entries). + // CHECK-NEXT: 0 | test3::F *test3::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test3::B *'): 8 non-virtual] + // CHECK-NEXT: 1 | void test3::D::z() + // CHECK-NEXT: 2 | test3::F *test3::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test3::C *'): 4 non-virtual] + // CHECK-NEXT: 3 | test3::F *test3::X::foo() + + // CHECK-LABEL: Thunks for 'test3::F *test3::X::foo()' (2 entries). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test3::C *'): 4 non-virtual] + // CHECK-NEXT: 1 | [return adjustment (to type 'struct test3::B *'): 8 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry). + // CHECK-NEXT: 3 | test3::F *test3::X::foo() + + virtual F* foo(); +}; + +void build_vftable(X *obj) { obj->foo(); } +} + +namespace test4 { +struct A { + virtual void g(); + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct E : D { + virtual C* foo(); +}; + +struct F : A, C { }; + +struct X : D, E { + // CHECK-LABEL: VFTable for 'test4::D' in 'test4::X' (3 entries). + // CHECK-NEXT: 0 | test4::F *test4::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual] + // CHECK-NEXT: 1 | void test4::D::z() + // CHECK-NEXT: 2 | test4::F *test4::X::foo() + + // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (1 entry). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual] + + // CHECK-LABEL: VFTable for 'test4::D' in 'test4::E' in 'test4::X' (4 entries). + // CHECK-NEXT: 0 | test4::F *test4::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void test4::D::z() + // CHECK-NEXT: 2 | test4::F *test4::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test4::C *'): 4 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 3 | test4::F *test4::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test4::F *'): 0 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (3 entries). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::F *'): 0 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | [return adjustment (to type 'struct test4::C *'): 4 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 2 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry). + // CHECK-NEXT: 2 | test4::F *test4::X::foo() + + virtual F* foo(); +}; + +void build_vftable(X *obj) { obj->foo(); } +} + +namespace test5 { +struct A { + virtual void g(); + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct X : A, D { + // CHECK-LABEL: VFTable for 'test5::A' in 'test5::X' (2 entries). + // CHECK-NEXT: 0 | void test5::A::g() + // CHECK-NEXT: 1 | void test5::A::h() + + // CHECK-LABEL: VFTable for 'test5::D' in 'test5::X' (3 entries). + // CHECK-NEXT: 0 | test5::C *test5::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test5::B *'): 4 non-virtual] + // CHECK-NEXT: 1 | void test5::D::z() + // CHECK-NEXT: 2 | test5::C *test5::X::foo() + + // CHECK-LABEL: Thunks for 'test5::C *test5::X::foo()' (1 entry). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test5::B *'): 4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 2 | test5::C *test5::X::foo() + + virtual C* foo(); +}; + +void build_vftable(X *obj) { obj->foo(); } +} + +namespace test6 { +struct A { + virtual void g(); + virtual void h(); +}; + +struct B { + virtual void g(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct D { + virtual B* foo(); + virtual void z(); +}; + +struct E : A, D { + virtual C* foo(); +}; + +struct F : A, C { }; + +struct X : E { + // CHECK-LABEL: VFTable for 'test6::A' in 'test6::E' in 'test6::X' (2 entries). + // CHECK-NEXT: 0 | void test6::A::g() + // CHECK-NEXT: 1 | void test6::A::h() + + // CHECK-LABEL: VFTable for 'test6::D' in 'test6::E' in 'test6::X' (4 entries). + // CHECK-NEXT: 0 | test6::F *test6::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test6::B *'): 8 non-virtual] + // CHECK-NEXT: 1 | void test6::D::z() + // CHECK-NEXT: 2 | test6::F *test6::X::foo() + // CHECK-NEXT: [return adjustment (to type 'struct test6::C *'): 4 non-virtual] + // CHECK-NEXT: 3 | test6::F *test6::X::foo() + + // CHECK-LABEL: Thunks for 'test6::F *test6::X::foo()' (2 entries). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct test6::C *'): 4 non-virtual] + // CHECK-NEXT: 1 | [return adjustment (to type 'struct test6::B *'): 8 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry). + // CHECK-NEXT: -- accessible via vfptr at offset 4 -- + // CHECK-NEXT: 3 | test6::F *test6::X::foo() + + virtual F* foo(); +}; + +void build_vftable(X *obj) { obj->foo(); } +} 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 new file mode 100644 index 0000000000000..957980aa95ec8 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp @@ -0,0 +1,140 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t +// RUN: FileCheck %s < %t +// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll + +namespace test1 { +struct A { + virtual void g(); + // Add an extra virtual method so it's easier to check for the absence of thunks. + virtual void h(); +}; + +struct B { + virtual void g(); // Collides with A::g if both are bases of some class. +}; + +// Overrides methods of two bases at the same time, thus needing thunks. +struct X : A, B { + // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (2 entries). + // CHECK-NEXT: 0 | void test1::X::g() + // CHECK-NEXT: 1 | void test1::A::h() + + // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (1 entry). + // CHECK-NEXT: 0 | void test1::X::g() + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'void test1::X::g()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry). + // CHECK-NEXT: 0 | void test1::X::g() + + // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@" + // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@" + + virtual void g(); +} x; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace test2 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C { + virtual void g(); +}; + +struct X : A, B, C { + // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry). + // CHECK-NEXT: 0 | void test2::A::f() + + // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries). + // CHECK-NEXT: 0 | void test2::X::g() + // CHECK-NEXT: 1 | void test2::B::h() + + // CHECK-LABEL: VFTable for 'test2::C' in 'test2::X' (1 entry). + // CHECK-NEXT: 0 | void test2::X::g() + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'void test2::X::g()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry). + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void test2::X::g() + + // MANGLING-DAG: @"\01??_7X@test2@@6BA@1@@" + // MANGLING-DAG: @"\01??_7X@test2@@6BB@1@@" + // MANGLING-DAG: @"\01??_7X@test2@@6BC@1@@" + + virtual void g(); +} x; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace test3 { +struct A { + virtual void f(); +}; + +struct B { + virtual void g(); + virtual void h(); +}; + +struct C: A, B { + // Overrides only the left child's method (A::f), needs no thunks. + virtual void f(); +}; + +struct D: A, B { + // Overrides only the right child's method (B::g), + // needs this adjustment but not thunks. + virtual void g(); +}; + +// Overrides methods of two bases at the same time, thus needing thunks. +struct X: C, D { + // CHECK-LABEL: VFTable for 'test3::A' in 'test3::C' in 'test3::X' (1 entry). + // CHECK-NEXT: 0 | void test3::X::f() + + // CHECK-LABEL: VFTable for 'test3::B' in 'test3::C' in 'test3::X' (2 entries). + // CHECK-NEXT: 0 | void test3::X::g() + // CHECK-NEXT: 1 | void test3::B::h() + + // CHECK-LABEL: VFTable for 'test3::A' in 'test3::D' in 'test3::X' (1 entry). + // CHECK-NEXT: 0 | void test3::X::f() + // CHECK-NEXT: [this adjustment: -8 non-virtual] + + // CHECK-LABEL: Thunks for 'void test3::X::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] + + // CHECK-LABEL: VFTable for 'test3::B' in 'test3::D' in 'test3::X' (2 entries). + // CHECK-NEXT: 0 | void test3::X::g() + // CHECK-NEXT: [this adjustment: -8 non-virtual] + // CHECK-NEXT: 1 | void test3::B::h() + + // CHECK-LABEL: Thunks for 'void test3::X::g()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] + + // CHECK-LABEL: VFTable indices for 'test3::X' (2 entries). + // CHECK-NEXT: via vfptr at offset 0 + // CHECK-NEXT: 0 | void test3::X::f() + // CHECK-NEXT: via vfptr at offset 4 + // CHECK-NEXT: 0 | void test3::X::g() + + virtual void f(); + virtual void g(); +} x; + +void build_vftable(X *obj) { obj->g(); } +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp new file mode 100644 index 0000000000000..a407766f8ed9f --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t +// RUN: FileCheck %s < %t + +struct A { + virtual ~A(); + virtual void z1(); +}; + +struct B { + virtual ~B(); +}; + +struct C : A, B { + // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries). + // CHECK-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-NEXT: 1 | void A::z1() + + // CHECK-LABEL: VFTable for 'B' in 'C' (1 entry). + // CHECK-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'C::~C()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'C' (1 entry). + // CHECK-NEXT: 0 | C::~C() [scalar deleting] + virtual ~C(); +}; + +void build_vftable(C *obj) { delete obj; } + +struct D { + // No virtual destructor here! + virtual void z4(); +}; + +struct E : D, B { + // Implicit virtual dtor here! + + // CHECK-LABEL: VFTable for 'D' in 'E' (1 entry). + // CHECK-NEXT: 0 | void D::z4() + + // CHECK-LABEL: VFTable for 'B' in 'E' (1 entry). + // CHECK-NEXT: 0 | E::~E() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'E::~E()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'E' (1 entry). + // CHECK-NEXT: -- accessible via vfptr at offset 4 -- + // CHECK-NEXT: 0 | E::~E() [scalar deleting] +}; + +void build_vftable(E *obj) { delete obj; } + +struct F : D, B { + // Implicit virtual dtor here! + + // CHECK-LABEL: VFTable for 'D' in 'F' (1 entry). + // CHECK-NEXT: 0 | void D::z4() + + // CHECK-LABEL: VFTable for 'B' in 'F' (1 entry). + // CHECK-NEXT: 0 | F::~F() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'F::~F()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'F' (1 entry). + // CHECK-NEXT: -- accessible via vfptr at offset 4 -- + // CHECK-NEXT: 0 | F::~F() [scalar deleting] +}; + +void build_vftable(F *obj) { delete obj; } + +struct G : F { + // CHECK-LABEL: VFTable for 'D' in 'F' in 'G' (1 entry). + // CHECK-NEXT: 0 | void D::z4() + + // CHECK-LABEL: VFTable for 'B' in 'F' in 'G' (1 entry). + // CHECK-NEXT: 0 | G::~G() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + + // CHECK-LABEL: Thunks for 'G::~G()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + + // CHECK-LABEL: VFTable indices for 'G' (1 entry). + // CHECK-NEXT: -- accessible via vfptr at offset 4 -- + // CHECK-NEXT: 0 | G::~G() [scalar deleting] + virtual ~G(); +}; + +void build_vftable(G *obj) { delete obj; } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp deleted file mode 100644 index d93dee11cdee4..0000000000000 --- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp +++ /dev/null @@ -1,579 +0,0 @@ -// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t - -// RUN: FileCheck --check-prefix=NO-THUNKS-Test1 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test2 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test3 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test4 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test5 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test6 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test7 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test8 %s < %t -// RUN: FileCheck --check-prefix=NO-THUNKS-Test9 %s < %t -// RUN: FileCheck --check-prefix=PURE-VIRTUAL-Test1 %s < %t -// RUN: FileCheck --check-prefix=THIS-THUNKS-Test1 %s < %t -// RUN: FileCheck --check-prefix=THIS-THUNKS-Test2 %s < %t -// RUN: FileCheck --check-prefix=THIS-THUNKS-Test3 %s < %t -// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test3 %s < %t -// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test5 %s < %t -// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test6 %s < %t -// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test7 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test1 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test2 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test3 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test6 %s < %t - -// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll - -struct Empty { - // Doesn't have a vftable! -}; - -struct A { - virtual void f(); -}; - -struct B { - virtual void g(); - // Add an extra virtual method so it's easier to check for the absence of thunks. - virtual void h(); -}; - -struct C { - virtual void g(); // Might "collide" with B::g if both are bases of some class. -}; - - -namespace no_thunks { - -struct Test1: A, B { - // NO-THUNKS-Test1: VFTable for 'A' in 'no_thunks::Test1' (1 entries) - // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f() - - // NO-THUNKS-Test1: VFTable for 'B' in 'no_thunks::Test1' (2 entries) - // NO-THUNKS-Test1-NEXT: 0 | void B::g() - // NO-THUNKS-Test1-NEXT: 1 | void B::h() - - // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries) - // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f() - - // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BA@@@" - // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BB@@@" - - // Overrides only the left child's method (A::f), needs no thunks. - virtual void f(); -}; - -Test1 t1; - -struct Test2: A, B { - // NO-THUNKS-Test2: VFTable for 'A' in 'no_thunks::Test2' (1 entries) - // NO-THUNKS-Test2-NEXT: 0 | void A::f() - - // NO-THUNKS-Test2: VFTable for 'B' in 'no_thunks::Test2' (2 entries) - // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g() - // NO-THUNKS-Test2-NEXT: 1 | void B::h() - - // NO-THUNKS-Test2: VFTable indices for 'no_thunks::Test2' (1 entries). - // NO-THUNKS-Test2-NEXT: via vfptr at offset 4 - // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g() - - // Overrides only the right child's method (B::g), needs this adjustment but - // not thunks. - virtual void g(); -}; - -Test2 t2; - -struct Test3: A, B { - // NO-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test3' (2 entries) - // NO-THUNKS-Test3-NEXT: 0 | void A::f() - // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i() - - // NO-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test3' (2 entries) - // NO-THUNKS-Test3-NEXT: 0 | void B::g() - // NO-THUNKS-Test3-NEXT: 1 | void B::h() - - // NO-THUNKS-Test3: VFTable indices for 'no_thunks::Test3' (1 entries). - // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i() - - // Only adds a new method. - virtual void i(); -}; - -Test3 t3; - -// Only the right base has a vftable, so it's laid out before the left one! -struct Test4 : Empty, A { - // NO-THUNKS-Test4: VFTable for 'A' in 'no_thunks::Test4' (1 entries) - // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f() - - // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries). - // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f() - - // MANGLING-DAG: @"\01??_7Test4@no_thunks@@6B@" - - virtual void f(); -}; - -Test4 t4; - -// 2-level structure with repeating subobject types, but no thunks needed. -struct Test5: Test1, Test2 { - // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries) - // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test1::f() - // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z() - - // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries) - // NO-THUNKS-Test5-NEXT: 0 | void B::g() - // NO-THUNKS-Test5-NEXT: 1 | void B::h() - - // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test5' (1 entries) - // NO-THUNKS-Test5-NEXT: 0 | void A::f() - - // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test5' (2 entries) - // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test2::g() - // NO-THUNKS-Test5-NEXT: 1 | void B::h() - - // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries). - // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z() - - // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test1@1@@" - // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test2@1@@" - // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test1@1@@" - // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test2@1@@" - - virtual void z(); -}; - -Test5 t5; - -struct Test6: Test1 { - // NO-THUNKS-Test6: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test6' (1 entries). - // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f() - - // NO-THUNKS-Test6: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test6' (2 entries). - // NO-THUNKS-Test6-NEXT: 0 | void B::g() - // NO-THUNKS-Test6-NEXT: 1 | void B::h() - - // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries). - // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f() - - // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BA@@@" - // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BB@@@" - - // Overrides both no_thunks::Test1::f and A::f. - virtual void f(); -}; - -Test6 t6; - -struct Test7: Test2 { - // NO-THUNKS-Test7: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test7' (1 entries). - // NO-THUNKS-Test7-NEXT: 0 | void A::f() - - // NO-THUNKS-Test7: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test7' (2 entries). - // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g() - // NO-THUNKS-Test7-NEXT: 1 | void B::h() - - // NO-THUNKS-Test7: VFTable indices for 'no_thunks::Test7' (1 entries). - // NO-THUNKS-Test7-NEXT: via vfptr at offset 4 - // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g() - - // Overrides both no_thunks::Test2::g and B::g. - virtual void g(); -}; - -Test7 t7; - -struct Test8: Test3 { - // NO-THUNKS-Test8: VFTable for 'A' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries). - // NO-THUNKS-Test8-NEXT: 0 | void A::f() - // NO-THUNKS-Test8-NEXT: 1 | void no_thunks::Test3::i() - - // NO-THUNKS-Test8: VFTable for 'B' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries). - // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g() - // NO-THUNKS-Test8-NEXT: 1 | void B::h() - - // NO-THUNKS-Test8: VFTable indices for 'no_thunks::Test8' (1 entries). - // NO-THUNKS-Test8-NEXT: via vfptr at offset 4 - // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g() - - // Overrides grandparent's B::g. - virtual void g(); -}; - -Test8 t8; - -struct D : A { - virtual void g(); -}; - -// Repeating subobject. -struct Test9: A, D { - // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::Test9' (2 entries). - // NO-THUNKS-Test9-NEXT: 0 | void A::f() - // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h() - - // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::D' in 'no_thunks::Test9' (2 entries). - // NO-THUNKS-Test9-NEXT: 0 | void A::f() - // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::D::g() - - // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries). - // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h() - - // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BA@@@" - // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BD@1@@" - - virtual void h(); -}; - -Test9 t9; -} - -namespace pure_virtual { -struct D { - virtual void g() = 0; - virtual void h(); -}; - - -struct Test1: A, D { - // PURE-VIRTUAL-Test1: VFTable for 'A' in 'pure_virtual::Test1' (1 entries) - // PURE-VIRTUAL-Test1-NEXT: 0 | void A::f() - - // PURE-VIRTUAL-Test1: VFTable for 'pure_virtual::D' in 'pure_virtual::Test1' (2 entries) - // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g() - // PURE-VIRTUAL-Test1-NEXT: 1 | void pure_virtual::D::h() - - // PURE-VIRTUAL-Test1: VFTable indices for 'pure_virtual::Test1' (1 entries). - // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4 - // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g() - - // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BA@@@" - // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BD@1@@" - - // Overrides only the right child's method (pure_virtual::D::g), needs this adjustment but - // not thunks. - virtual void g(); -}; - -Test1 t1; -} - -namespace this_adjustment { - -// Overrides methods of two bases at the same time, thus needing thunks. -struct Test1 : B, C { - // THIS-THUNKS-Test1: VFTable for 'B' in 'this_adjustment::Test1' (2 entries). - // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g() - // THIS-THUNKS-Test1-NEXT: 1 | void B::h() - - // THIS-THUNKS-Test1: VFTable for 'C' in 'this_adjustment::Test1' (1 entries). - // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g() - // THIS-THUNKS-Test1-NEXT: [this adjustment: -4 non-virtual] - - // THIS-THUNKS-Test1: Thunks for 'void this_adjustment::Test1::g()' (1 entry). - // THIS-THUNKS-Test1-NEXT: 0 | [this adjustment: -4 non-virtual] - - // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1 entries). - // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g() - - // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BB@@@" - // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BC@@@" - - virtual void g(); -}; - -Test1 t1; - -struct Test2 : A, B, C { - // THIS-THUNKS-Test2: VFTable for 'A' in 'this_adjustment::Test2' (1 entries). - // THIS-THUNKS-Test2-NEXT: 0 | void A::f() - - // THIS-THUNKS-Test2: VFTable for 'B' in 'this_adjustment::Test2' (2 entries). - // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g() - // THIS-THUNKS-Test2-NEXT: 1 | void B::h() - - // THIS-THUNKS-Test2: VFTable for 'C' in 'this_adjustment::Test2' (1 entries). - // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g() - // THIS-THUNKS-Test2-NEXT: [this adjustment: -4 non-virtual] - - // THIS-THUNKS-Test2: Thunks for 'void this_adjustment::Test2::g()' (1 entry). - // THIS-THUNKS-Test2-NEXT: 0 | [this adjustment: -4 non-virtual] - - // THIS-THUNKS-Test2: VFTable indices for 'this_adjustment::Test2' (1 entries). - // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4 - // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g() - - // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BA@@@" - // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BB@@@" - // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BC@@@" - - virtual void g(); -}; - -Test2 t2; - -// Overrides methods of two bases at the same time, thus needing thunks. -struct Test3: no_thunks::Test1, no_thunks::Test2 { - // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test1' in 'this_adjustment::Test3' (1 entries). - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f() - - // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test1' in 'this_adjustment::Test3' (2 entries). - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g() - // THIS-THUNKS-Test3-NEXT: 1 | void B::h() - - // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test2' in 'this_adjustment::Test3' (1 entries). - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f() - // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual] - - // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::f()' (1 entry). - // THIS-THUNKS-Test3-NEXT: 0 | [this adjustment: -8 non-virtual] - - // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test2' in 'this_adjustment::Test3' (2 entries). - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g() - // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual] - // THIS-THUNKS-Test3-NEXT: 1 | void B::h() - - // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::g()' (1 entry). - // THIS-THUNKS-Test3-NEXT: 0 | [this adjustment: -8 non-virtual] - - // THIS-THUNKS-Test3: VFTable indices for 'this_adjustment::Test3' (2 entries). - // THIS-THUNKS-Test3-NEXT: via vfptr at offset 0 - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f() - // THIS-THUNKS-Test3-NEXT: via vfptr at offset 4 - // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g() - - virtual void f(); - virtual void g(); -}; - -Test3 t3; -} - -namespace vdtor { -struct Test1 { - virtual ~Test1(); - virtual void z1(); -}; - -struct Test2 { - virtual ~Test2(); -}; - -struct Test3 : Test1, Test2 { - // VDTOR-THUNKS-Test3: VFTable for 'vdtor::Test1' in 'vdtor::Test3' (2 entries). - // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting] - // VDTOR-THUNKS-Test3-NEXT: 1 | void vdtor::Test1::z1() - - // VDTOR-THUNKS-Test3: VFTable for 'vdtor::Test2' in 'vdtor::Test3' (1 entries). - // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting] - // VDTOR-THUNKS-Test3-NEXT: [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test3: Thunks for 'vdtor::Test3::~Test3()' (1 entry). - // VDTOR-THUNKS-Test3-NEXT: 0 | [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test3: VFTable indices for 'vdtor::Test3' (1 entries). - // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting] - virtual ~Test3(); -}; - -Test3 t3; - -struct Test4 { - // No virtual destructor here! - virtual void z4(); -}; - -struct Test5 : Test4, Test2 { - // Implicit virtual dtor here! - - // VDTOR-THUNKS-Test5: VFTable for 'vdtor::Test4' in 'vdtor::Test5' (1 entries). - // VDTOR-THUNKS-Test5-NEXT: 0 | void vdtor::Test4::z4() - - // VDTOR-THUNKS-Test5: VFTable for 'vdtor::Test2' in 'vdtor::Test5' (1 entries). - // VDTOR-THUNKS-Test5-NEXT: 0 | vdtor::Test5::~Test5() [scalar deleting] - // VDTOR-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test5: Thunks for 'vdtor::Test5::~Test5()' (1 entry). - // VDTOR-THUNKS-Test5-NEXT: 0 | [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test5: VFTable indices for 'vdtor::Test5' (1 entries). - // VDTOR-THUNKS-Test5-NEXT: -- accessible via vfptr at offset 4 -- - // VDTOR-THUNKS-Test5-NEXT: 0 | vdtor::Test5::~Test5() [scalar deleting] -}; - -Test5 t5; - -struct Test6 : Test4, Test2 { - // Implicit virtual dtor here! - - // VDTOR-THUNKS-Test6: VFTable for 'vdtor::Test4' in 'vdtor::Test6' (1 entries). - // VDTOR-THUNKS-Test6-NEXT: 0 | void vdtor::Test4::z4() - - // VDTOR-THUNKS-Test6: VFTable for 'vdtor::Test2' in 'vdtor::Test6' (1 entries). - // VDTOR-THUNKS-Test6-NEXT: 0 | vdtor::Test6::~Test6() [scalar deleting] - // VDTOR-THUNKS-Test6-NEXT: [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test6: Thunks for 'vdtor::Test6::~Test6()' (1 entry). - // VDTOR-THUNKS-Test6-NEXT: 0 | [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test6: VFTable indices for 'vdtor::Test6' (1 entries). - // VDTOR-THUNKS-Test6-NEXT: -- accessible via vfptr at offset 4 -- - // VDTOR-THUNKS-Test6-NEXT: 0 | vdtor::Test6::~Test6() [scalar deleting] -}; - -Test6 t6; - -struct Test7 : Test5 { - // VDTOR-THUNKS-Test7: VFTable for 'vdtor::Test4' in 'vdtor::Test5' in 'vdtor::Test7' (1 entries). - // VDTOR-THUNKS-Test7-NEXT: 0 | void vdtor::Test4::z4() - - // VDTOR-THUNKS-Test7: VFTable for 'vdtor::Test2' in 'vdtor::Test5' in 'vdtor::Test7' (1 entries). - // VDTOR-THUNKS-Test7-NEXT: 0 | vdtor::Test7::~Test7() [scalar deleting] - // VDTOR-THUNKS-Test7-NEXT: [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test7: Thunks for 'vdtor::Test7::~Test7()' (1 entry). - // VDTOR-THUNKS-Test7-NEXT: 0 | [this adjustment: -4 non-virtual] - - // VDTOR-THUNKS-Test7: VFTable indices for 'vdtor::Test7' (1 entries). - // VDTOR-THUNKS-Test7-NEXT: -- accessible via vfptr at offset 4 -- - // VDTOR-THUNKS-Test7-NEXT: 0 | vdtor::Test7::~Test7() [scalar deleting] - virtual ~Test7(); -}; - -Test7 t7; - -} - -namespace return_adjustment { - -struct Ret1 { - virtual C* foo(); - virtual void z(); -}; - -struct Test1 : Ret1 { - // RET-THUNKS-Test1: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' (3 entries). - // RET-THUNKS-Test1-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test1::foo() - // RET-THUNKS-Test1-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test1-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo() - - // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1 entries). - // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo() - - // MANGLING-DAG: @"\01??_7Test1@return_adjustment@@6B@" - - virtual this_adjustment::Test1* foo(); -}; - -Test1 t1; - -struct Ret2 : B, this_adjustment::Test1 { }; - -struct Test2 : Test1 { - // RET-THUNKS-Test2: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test2' (4 entries). - // RET-THUNKS-Test2-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test2::foo() - // RET-THUNKS-Test2-NEXT: [return adjustment: 8 non-virtual] - // RET-THUNKS-Test2-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test2-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test2::foo() - // RET-THUNKS-Test2-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo() - - // RET-THUNKS-Test2: VFTable indices for 'return_adjustment::Test2' (1 entries). - // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo() - - virtual Ret2* foo(); -}; - -Test2 t2; - -struct Test3: B, Ret1 { - // RET-THUNKS-Test3: VFTable for 'B' in 'return_adjustment::Test3' (2 entries). - // RET-THUNKS-Test3-NEXT: 0 | void B::g() - // RET-THUNKS-Test3-NEXT: 1 | void B::h() - - // RET-THUNKS-Test3: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' (3 entries). - // RET-THUNKS-Test3-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test3::foo() - // RET-THUNKS-Test3-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test3-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo() - - // RET-THUNKS-Test3: VFTable indices for 'return_adjustment::Test3' (1 entries). - // RET-THUNKS-Test3-NEXT: via vfptr at offset 4 - // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo() - - virtual this_adjustment::Test1* foo(); -}; - -Test3 t3; - -struct Test4 : Test3 { - // RET-THUNKS-Test4: VFTable for 'B' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (2 entries). - // RET-THUNKS-Test4-NEXT: 0 | void B::g() - // RET-THUNKS-Test4-NEXT: 1 | void B::h() - - // RET-THUNKS-Test4: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (4 entries). - // RET-THUNKS-Test4-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test4::foo() - // RET-THUNKS-Test4-NEXT: [return adjustment: 8 non-virtual] - // RET-THUNKS-Test4-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test4-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test4::foo() - // RET-THUNKS-Test4-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo() - - // RET-THUNKS-Test4: VFTable indices for 'return_adjustment::Test4' (1 entries). - // RET-THUNKS-Test4-NEXT: -- accessible via vfptr at offset 4 -- - // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo() - - virtual Ret2* foo(); -}; - -Test4 t4; - -struct Test5 : Ret1, Test1 { - // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test5' (3 entries). - // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual] - // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - - // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test5' (4 entries). - // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual] - // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual] - // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - // RET-THUNKS-Test5-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual] - // RET-THUNKS-Test5-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual] - - // RET-THUNKS-Test5: VFTable indices for 'return_adjustment::Test5' (1 entries). - // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo() - - virtual Ret2* foo(); -}; - -Test5 t5; - -struct Ret3 : this_adjustment::Test1 { }; - -struct Test6 : Test1 { - virtual Ret3* foo(); - // RET-THUNKS-Test6: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test6' (4 entries). - // RET-THUNKS-Test6-NEXT: 0 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - // RET-THUNKS-Test6-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test6-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test6-NEXT: 2 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - - // RET-THUNKS-Test6: VFTable indices for 'return_adjustment::Test6' (1 entries). - // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo() -}; - -Test6 t6; - -} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp new file mode 100644 index 0000000000000..a4a21106c6856 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -fno-rtti %s -emit-llvm -o %t -triple=i386-pc-win32 -fdump-vtable-layouts 2>&1 | FileCheck --check-prefix=VFTABLES %s +// RUN: FileCheck --check-prefix=GLOBALS %s < %t +// RUN: FileCheck --check-prefix=CODEGEN %s < %t + +namespace test1 { + +// Some covariant types. +struct A { int a; }; +struct B { int b; }; +struct C : A, B { int c; }; +struct D : C { int d; }; +struct E : D { int e; }; + +// One base class and two overrides, all with covariant return types. +struct H { virtual B *foo(); }; +struct I : H { virtual C *foo(); }; +struct J : I { virtual D *foo(); J(); }; +struct K : J { virtual E *foo(); K(); }; + +J::J() {} + +// VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' (3 entries). +// VFTABLES-NEXT: 0 | test1::D *test1::J::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual] +// VFTABLES-NEXT: 1 | test1::D *test1::J::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual] +// VFTABLES-NEXT: 2 | test1::D *test1::J::foo() + +// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +// GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ" +// GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ" +// GLOBALS: @"\01?foo@J@test1@@UAEPAUD@2@XZ" + +K::K() {} + +// VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' in 'test1::K' (4 entries). +// VFTABLES-NEXT: 0 | test1::E *test1::K::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual] +// VFTABLES-NEXT: 1 | test1::E *test1::K::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual] +// VFTABLES-NEXT: 2 | test1::E *test1::K::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test1::D *'): 0 non-virtual] +// VFTABLES-NEXT: 3 | test1::E *test1::K::foo() + +// Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of +// which are trivial. +// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant [4 x i8*] +// GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ" +// GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ" +// GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ" +// GLOBALS: @"\01?foo@K@test1@@UAEPAUE@2@XZ" + +// This thunk has a return adjustment. +// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUB@2@XZ" +// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ" +// CODEGEN: icmp {{.*}}, null +// CODEGEN: getelementptr +// CODEGEN: ret + +// These two don't. +// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUC@2@XZ" +// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ" +// CODEGEN-NEXT: ret + +// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUD@2@XZ" +// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ" +// CODEGEN-NEXT: ret + +} + +namespace test2 { + +// Covariant types. D* is not trivially convertible to C*. +struct A { int a; }; +struct B { int b; }; +struct C : B { int c; }; +struct D : A, C { int d; }; +struct E : D { int e; }; + +// J's foo will require an adjusting thunk, and K will require a trivial thunk. +struct H { virtual B *foo(); }; +struct I : H { virtual C *foo(); }; +struct J : I { virtual D *foo(); J(); }; +struct K : J { virtual E *foo(); K(); }; + +J::J() {} + +// VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' (2 entries). +// VFTABLES-NEXT: 0 | test2::D *test2::J::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual] +// VFTABLES-NEXT: 1 | test2::D *test2::J::foo() + +// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] + +K::K() {} + +// VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' in 'test2::K' (3 entries). +// VFTABLES-NEXT: 0 | test2::E *test2::K::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual] +// VFTABLES-NEXT: 1 | test2::E *test2::K::foo() +// VFTABLES-NEXT: [return adjustment (to type 'struct test2::D *'): 0 non-virtual] +// VFTABLES-NEXT: 2 | test2::E *test2::K::foo() + +// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] + +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index 6fe12b0ef07ba..d453f5c55aed1 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -1,29 +1,17 @@ -// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t // RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll // RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll -// RUN: FileCheck --check-prefix=CHECK-A %s < %t -// RUN: FileCheck --check-prefix=CHECK-B %s < %t -// RUN: FileCheck --check-prefix=CHECK-C %s < %t -// RUN: FileCheck --check-prefix=CHECK-D %s < %t -// RUN: FileCheck --check-prefix=CHECK-E %s < %t -// RUN: FileCheck --check-prefix=CHECK-F %s < %t -// RUN: FileCheck --check-prefix=CHECK-G %s < %t -// RUN: FileCheck --check-prefix=CHECK-I %s < %t -// RUN: FileCheck --check-prefix=CHECK-J %s < %t -// RUN: FileCheck --check-prefix=CHECK-K %s < %t -// RUN: FileCheck --check-prefix=CHECK-L %s < %t -// RUN: FileCheck --check-prefix=CHECK-M %s < %t -// RUN: FileCheck --check-prefix=CHECK-N %s < %t +// RUN: FileCheck %s < %t struct A { - // CHECK-A: VFTable for 'A' (3 entries) - // CHECK-A-NEXT: 0 | void A::f() - // CHECK-A-NEXT: 1 | void A::g() - // CHECK-A-NEXT: 2 | void A::h() - // CHECK-A: VFTable indices for 'A' (3 entries) - // CHECK-A-NEXT: 0 | void A::f() - // CHECK-A-NEXT: 1 | void A::g() - // CHECK-A-NEXT: 2 | void A::h() + // CHECK-LABEL: VFTable for 'A' (3 entries) + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() + // CHECK-LABEL: VFTable indices for 'A' (3 entries) + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() virtual void f(); virtual void g(); @@ -32,18 +20,19 @@ struct A { }; A a; // EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +void use(A *obj) { obj->f(); } struct B : A { - // CHECK-B: VFTable for 'A' in 'B' (5 entries) - // CHECK-B-NEXT: 0 | void B::f() - // CHECK-B-NEXT: 1 | void A::g() - // CHECK-B-NEXT: 2 | void A::h() - // CHECK-B-NEXT: 3 | void B::i() - // CHECK-B-NEXT: 4 | void B::j() - // CHECK-B: VFTable indices for 'B' (3 entries) - // CHECK-B-NEXT: 0 | void B::f() - // CHECK-B-NEXT: 3 | void B::i() - // CHECK-B-NEXT: 4 | void B::j() + // CHECK-LABEL: VFTable for 'A' in 'B' (5 entries) + // CHECK-NEXT: 0 | void B::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() + // CHECK-NEXT: 3 | void B::i() + // CHECK-NEXT: 4 | void B::j() + // CHECK-LABEL: VFTable indices for 'B' (3 entries) + // CHECK-NEXT: 0 | void B::f() + // CHECK-NEXT: 3 | void B::i() + // CHECK-NEXT: 4 | void B::j() virtual void f(); // overrides A::f() virtual void i(); @@ -51,45 +40,48 @@ struct B : A { }; B b; // EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +void use(B *obj) { obj->f(); } struct C { - // CHECK-C: VFTable for 'C' (2 entries) - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] - // CHECK-C-NEXT: 1 | void C::f() - // CHECK-C: VFTable indices for 'C' (2 entries). - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] - // CHECK-C-NEXT: 1 | void C::f() + // CHECK-LABEL: VFTable for 'C' (2 entries) + // CHECK-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-NEXT: 1 | void C::f() + // CHECK-LABEL: VFTable indices for 'C' (2 entries). + // CHECK-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-NEXT: 1 | void C::f() virtual ~C(); virtual void f(); }; void C::f() {} // NO-VFTABLE-NOT: @"\01??_7C@@6B@" +void use(C *obj) { obj->f(); } struct D { - // CHECK-D: VFTable for 'D' (2 entries) - // CHECK-D-NEXT: 0 | void D::f() - // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] - // CHECK-D: VFTable indices for 'D' (2 entries) - // CHECK-D-NEXT: 0 | void D::f() - // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] + // CHECK-LABEL: VFTable for 'D' (2 entries) + // CHECK-NEXT: 0 | void D::f() + // CHECK-NEXT: 1 | D::~D() [scalar deleting] + // CHECK-LABEL: VFTable indices for 'D' (2 entries) + // CHECK-NEXT: 0 | void D::f() + // CHECK-NEXT: 1 | D::~D() [scalar deleting] virtual void f(); virtual ~D(); }; D d; // EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +void use(D *obj) { obj->f(); } struct E : A { - // CHECK-E: VFTable for 'A' in 'E' (5 entries) - // CHECK-E-NEXT: 0 | void A::f() - // CHECK-E-NEXT: 1 | void A::g() - // CHECK-E-NEXT: 2 | void A::h() - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] - // CHECK-E-NEXT: 4 | void E::i() - // CHECK-E: VFTable indices for 'E' (2 entries). - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] - // CHECK-E-NEXT: 4 | void E::i() + // CHECK-LABEL: VFTable for 'A' in 'E' (5 entries) + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() + // CHECK-NEXT: 3 | E::~E() [scalar deleting] + // CHECK-NEXT: 4 | void E::i() + // CHECK-LABEL: VFTable indices for 'E' (2 entries). + // CHECK-NEXT: 3 | E::~E() [scalar deleting] + // CHECK-NEXT: 4 | void E::i() // ~E would be the key method, but it isn't used, and MS ABI has no key // methods. @@ -98,36 +90,38 @@ struct E : A { }; void E::i() {} // NO-VFTABLE-NOT: @"\01??_7E@@6B@" +void use(E *obj) { obj->i(); } struct F : A { - // CHECK-F: VFTable for 'A' in 'F' (5 entries) - // CHECK-F-NEXT: 0 | void A::f() - // CHECK-F-NEXT: 1 | void A::g() - // CHECK-F-NEXT: 2 | void A::h() - // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] - // CHECK-F: VFTable indices for 'F' (2 entries). - // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] + // CHECK-LABEL: VFTable for 'A' in 'F' (5 entries) + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() + // CHECK-NEXT: 3 | void F::i() + // CHECK-NEXT: 4 | F::~F() [scalar deleting] + // CHECK-LABEL: VFTable indices for 'F' (2 entries). + // CHECK-NEXT: 3 | void F::i() + // CHECK-NEXT: 4 | F::~F() [scalar deleting] virtual void i(); virtual ~F(); }; F f; // EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +void use(F *obj) { obj->i(); } struct G : E { - // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries) - // CHECK-G-NEXT: 0 | void G::f() - // CHECK-G-NEXT: 1 | void A::g() - // CHECK-G-NEXT: 2 | void A::h() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] - // CHECK-G-NEXT: 4 | void E::i() - // CHECK-G-NEXT: 5 | void G::j() - // CHECK-G: VFTable indices for 'G' (3 entries). - // CHECK-G-NEXT: 0 | void G::f() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] - // CHECK-G-NEXT: 5 | void G::j() + // CHECK-LABEL: VFTable for 'A' in 'E' in 'G' (6 entries) + // CHECK-NEXT: 0 | void G::f() + // CHECK-NEXT: 1 | void A::g() + // CHECK-NEXT: 2 | void A::h() + // CHECK-NEXT: 3 | G::~G() [scalar deleting] + // CHECK-NEXT: 4 | void E::i() + // CHECK-NEXT: 5 | void G::j() + // CHECK-LABEL: VFTable indices for 'G' (3 entries). + // CHECK-NEXT: 0 | void G::f() + // CHECK-NEXT: 3 | G::~G() [scalar deleting] + // CHECK-NEXT: 5 | void G::j() virtual void f(); // overrides A::f() virtual ~G(); @@ -135,6 +129,7 @@ struct G : E { }; void G::j() {} // NO-VFTABLE-NOT: @"\01??_7G@@6B@" +void use(G *obj) { obj->j(); } // Test that the usual Itanium-style key method does not emit a vtable. struct H { @@ -146,23 +141,24 @@ void H::f() {} struct Empty { }; struct I : Empty { - // CHECK-I: VFTable for 'I' (2 entries) - // CHECK-I-NEXT: 0 | void I::f() - // CHECK-I-NEXT: 1 | void I::g() + // CHECK-LABEL: VFTable for 'I' (2 entries) + // CHECK-NEXT: 0 | void I::f() + // CHECK-NEXT: 1 | void I::g() virtual void f(); virtual void g(); }; I i; +void use(I *obj) { obj->f(); } struct J { - // CHECK-J: VFTable for 'J' (6 entries) - // CHECK-J-NEXT: 0 | void J::foo(long) - // CHECK-J-NEXT: 1 | void J::foo(int) - // CHECK-J-NEXT: 2 | void J::foo(short) - // CHECK-J-NEXT: 3 | void J::bar(long) - // CHECK-J-NEXT: 4 | void J::bar(int) - // CHECK-J-NEXT: 5 | void J::bar(short) + // CHECK-LABEL: VFTable for 'J' (6 entries) + // CHECK-NEXT: 0 | void J::foo(long) + // CHECK-NEXT: 1 | void J::foo(int) + // CHECK-NEXT: 2 | void J::foo(short) + // CHECK-NEXT: 3 | void J::bar(long) + // CHECK-NEXT: 4 | void J::bar(int) + // CHECK-NEXT: 5 | void J::bar(short) virtual void foo(short); virtual void bar(short); virtual void foo(int); @@ -172,36 +168,38 @@ struct J { }; J j; +void use(J *obj) { obj->foo(42); } struct K : J { - // CHECK-K: VFTable for 'J' in 'K' (9 entries) - // CHECK-K-NEXT: 0 | void J::foo(long) - // CHECK-K-NEXT: 1 | void J::foo(int) - // CHECK-K-NEXT: 2 | void J::foo(short) - // CHECK-K-NEXT: 3 | void J::bar(long) - // CHECK-K-NEXT: 4 | void J::bar(int) - // CHECK-K-NEXT: 5 | void J::bar(short) - // CHECK-K-NEXT: 6 | void K::bar(double) - // CHECK-K-NEXT: 7 | void K::bar(float) - // CHECK-K-NEXT: 8 | void K::foo(float) + // CHECK-LABEL: VFTable for 'J' in 'K' (9 entries) + // CHECK-NEXT: 0 | void J::foo(long) + // CHECK-NEXT: 1 | void J::foo(int) + // CHECK-NEXT: 2 | void J::foo(short) + // CHECK-NEXT: 3 | void J::bar(long) + // CHECK-NEXT: 4 | void J::bar(int) + // CHECK-NEXT: 5 | void J::bar(short) + // CHECK-NEXT: 6 | void K::bar(double) + // CHECK-NEXT: 7 | void K::bar(float) + // CHECK-NEXT: 8 | void K::foo(float) virtual void bar(float); virtual void foo(float); virtual void bar(double); }; K k; +void use(K *obj) { obj->foo(42.0f); } struct L : J { - // CHECK-L: VFTable for 'J' in 'L' (9 entries) - // CHECK-L-NEXT: 0 | void J::foo(long) - // CHECK-L-NEXT: 1 | void L::foo(int) - // CHECK-L-NEXT: 2 | void J::foo(short) - // CHECK-L-NEXT: 3 | void J::bar(long) - // CHECK-L-NEXT: 4 | void J::bar(int) - // CHECK-L-NEXT: 5 | void J::bar(short) - // CHECK-L-NEXT: 6 | void L::foo(float) - // CHECK-L-NEXT: 7 | void L::bar(double) - // CHECK-L-NEXT: 8 | void L::bar(float) + // CHECK-LABEL: VFTable for 'J' in 'L' (9 entries) + // CHECK-NEXT: 0 | void J::foo(long) + // CHECK-NEXT: 1 | void L::foo(int) + // CHECK-NEXT: 2 | void J::foo(short) + // CHECK-NEXT: 3 | void J::bar(long) + // CHECK-NEXT: 4 | void J::bar(int) + // CHECK-NEXT: 5 | void J::bar(short) + // CHECK-NEXT: 6 | void L::foo(float) + // CHECK-NEXT: 7 | void L::bar(double) + // CHECK-NEXT: 8 | void L::bar(float) // This case is interesting. Since the J::foo(int) override is the first method in // the class, foo(float) precedes the bar(double) and bar(float) in the vftable. @@ -212,20 +210,21 @@ struct L : J { }; L l; +void use(L *obj) { obj->foo(42.0f); } struct M : J { - // CHECK-M: VFTable for 'J' in 'M' (11 entries) - // CHECK-M-NEXT: 0 | void J::foo(long) - // CHECK-M-NEXT: 1 | void M::foo(int) - // CHECK-M-NEXT: 2 | void J::foo(short) - // CHECK-M-NEXT: 3 | void J::bar(long) - // CHECK-M-NEXT: 4 | void J::bar(int) - // CHECK-M-NEXT: 5 | void J::bar(short) - // CHECK-M-NEXT: 6 | void M::foo(float) - // CHECK-M-NEXT: 7 | void M::spam(long) - // CHECK-M-NEXT: 8 | void M::spam(int) - // CHECK-M-NEXT: 9 | void M::bar(double) - // CHECK-M-NEXT: 10 | void M::bar(float) + // CHECK-LABEL: VFTable for 'J' in 'M' (11 entries) + // CHECK-NEXT: 0 | void J::foo(long) + // CHECK-NEXT: 1 | void M::foo(int) + // CHECK-NEXT: 2 | void J::foo(short) + // CHECK-NEXT: 3 | void J::bar(long) + // CHECK-NEXT: 4 | void J::bar(int) + // CHECK-NEXT: 5 | void J::bar(short) + // CHECK-NEXT: 6 | void M::foo(float) + // CHECK-NEXT: 7 | void M::spam(long) + // CHECK-NEXT: 8 | void M::spam(int) + // CHECK-NEXT: 9 | void M::bar(double) + // CHECK-NEXT: 10 | void M::bar(float) virtual void foo(int); virtual void spam(int); @@ -236,13 +235,14 @@ struct M : J { }; M m; +void use(M *obj) { obj->foo(42.0f); } struct N { - // CHECK-N: VFTable for 'N' (4 entries) - // CHECK-N-NEXT: 0 | void N::operator+(int) - // CHECK-N-NEXT: 1 | void N::operator+(short) - // CHECK-N-NEXT: 2 | void N::operator*(int) - // CHECK-N-NEXT: 3 | void N::operator*(short) + // CHECK-LABEL: VFTable for 'N' (4 entries) + // CHECK-NEXT: 0 | void N::operator+(int) + // CHECK-NEXT: 1 | void N::operator+(short) + // CHECK-NEXT: 2 | void N::operator*(int) + // CHECK-NEXT: 3 | void N::operator*(short) virtual void operator+(short); virtual void operator*(short); virtual void operator+(int); @@ -250,3 +250,42 @@ struct N { }; N n; +void use(N *obj) { obj->operator+(42); } + +struct O { virtual A *f(); }; +struct P : O { virtual B *f(); }; +P p; +void use(O *obj) { obj->f(); } +void use(P *obj) { obj->f(); } +// CHECK-LABEL: VFTable for 'O' (1 entry) +// CHECK-NEXT: 0 | A *O::f() + +// CHECK-LABEL: VFTable for 'O' in 'P' (1 entry) +// CHECK-NEXT: 0 | B *P::f() + +struct Q { + // CHECK-LABEL: VFTable for 'Q' (2 entries) + // CHECK-NEXT: 0 | void Q::foo(int) + // CHECK-NEXT: 1 | void Q::bar(int) + void foo(short); + void bar(short); + virtual void bar(int); + virtual void foo(int); +}; + +Q q; +void use(Q *obj) { obj->foo(42); } + +// Inherited non-virtual overloads don't participate in the ordering. +struct R : Q { + // CHECK-LABEL: VFTable for 'Q' in 'R' (4 entries) + // CHECK-NEXT: 0 | void Q::foo(int) + // CHECK-NEXT: 1 | void Q::bar(int) + // CHECK-NEXT: 2 | void R::bar(long) + // CHECK-NEXT: 3 | void R::foo(long) + virtual void bar(long); + virtual void foo(long); +}; + +R r; +void use(R *obj) { obj->foo(42l); } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp index 3fef0e4093496..f63808a898734 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp @@ -1,19 +1,9 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -fdump-vtable-layouts %s -o %t.ll -cxx-abi microsoft -triple=i386-pc-win32 >%t -// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-A %s < %t -// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-B %s < %t -// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-C %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-A %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-B %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-C %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-E %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-F %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-G %s < %t -// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-H %s < %t -// RUN: FileCheck --check-prefix=VTABLE-PR17738-A %s < %t +// RUN: %clang_cc1 -fno-rtti -emit-llvm -fdump-vtable-layouts %s -o %t.ll -triple=i386-pc-win32 > %t +// RUN: FileCheck %s < %t // RUN: FileCheck --check-prefix=MANGLING %s < %t.ll // For now, just make sure x86_64 doesn't crash. -// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -fdump-vtable-layouts %s -cxx-abi microsoft -triple=x86_64-pc-win32 >/dev/null +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -fdump-vtable-layouts %s -triple=x86_64-pc-win32 > /dev/null struct V1 { virtual void f(); @@ -64,11 +54,17 @@ namespace simple { // jmp Method@Class struct A : virtual V1 { - // VTABLE-SIMPLE-A: VFTable for 'V1' in 'simple::A' (2 entries). - // VTABLE-SIMPLE-A-NEXT: 0 | void simple::A::f() - // VTABLE-SIMPLE-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] - // VTABLE-SIMPLE-A-NEXT: 1 | simple::A::~A() [scalar deleting] - // VTABLE-SIMPLE-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' (2 entries). + // CHECK-NEXT: 0 | void simple::A::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-NEXT: 1 | simple::A::~A() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'simple::A::~A()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual] virtual void f(); // MANGLING-DAG: @"\01?f@A@simple@@$4PPPPPPPM@A@AEXXZ" @@ -78,18 +74,28 @@ struct A : virtual V1 { }; A a; +void use(A *obj) { obj->f(); } struct B : virtual V3 { - // VTABLE-SIMPLE-B: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries). - // VTABLE-SIMPLE-B-NEXT: 0 | void Z::g() - // VTABLE-SIMPLE-B-NEXT: 1 | simple::B::~B() [scalar deleting] - // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries). + // CHECK-NEXT: 0 | void Z::g() + // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries). + // CHECK-NEXT: 0 | void simple::B::f() + // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] + // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] - // VTABLE-SIMPLE-B: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries). - // VTABLE-SIMPLE-B-NEXT: 0 | void simple::B::f() - // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] - // VTABLE-SIMPLE-B-NEXT: 1 | simple::B::~B() [scalar deleting] - // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] + // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual] // FIXME: The vtordisp thunk should only get emitted for a constructor // if "this" leaves scope. @@ -104,24 +110,40 @@ struct B : virtual V3 { }; B b; +void use(B *obj) { obj->f(); } struct C : virtual V4 { - // VTABLE-SIMPLE-C: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries). - // VTABLE-SIMPLE-C-NEXT: 0 | void Z::g() - // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting] - // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] - - // VTABLE-SIMPLE-C: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries). - // VTABLE-SIMPLE-C-NEXT: 0 | void simple::C::f() - // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] - // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting] - // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] - - // VTABLE-SIMPLE-C: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries). - // VTABLE-SIMPLE-C-NEXT: 0 | void simple::C::f() - // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual] - // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting] - // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual] + // CHECK-LABEL: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries). + // CHECK-NEXT: 0 | void Z::g() + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries). + // CHECK-NEXT: 0 | void simple::C::f() + // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] + + // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual] + + // CHECK-LABEL: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries). + // CHECK-NEXT: 0 | void simple::C::f() + // CHECK-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual] + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual] + + // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -12 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -4 non-virtual] int x; virtual void f(); @@ -134,6 +156,68 @@ struct C : virtual V4 { }; C c; +void use(C *obj) { obj->f(); } + +class D : B { + // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'simple::D' (2 entries). + // CHECK-NEXT: 0 | void simple::B::f() + // CHECK-NEXT: [this adjustment: vtordisp at -12, -4 non-virtual] + // CHECK-NEXT: 1 | simple::D::~D() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] + D(); + int z; + + // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@3AEXXZ" +}; + +D::D() {} + +struct E : V3 { + virtual void f(); +}; + +struct F : virtual E { + // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' (2 entries). + // CHECK-NEXT: 0 | void simple::F::g() + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' (2 entries). + // CHECK-NEXT: 0 | void simple::E::f() + // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] + + F(); + virtual void g(); // Force a vtordisp. + int f; + + // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z + // MANGLING-DAG: ?f@E@simple@@UAEXXZ{{.*}}??_EF@simple@@$4PPPPPPPE@7AEPAXI@Z +}; + +F::F() {} + +struct G : F { + // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries). + // CHECK-NEXT: 0 | void simple::F::g() + // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual] + // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries). + // CHECK-NEXT: 0 | void simple::E::f() + // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] + + G(); + int g; + + // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z" + // MANGLING-DAG: @"\01?f@E@simple@@UAEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z" +}; + +G::G() {} } namespace extended { @@ -152,12 +236,16 @@ namespace extended { // jmp Method@Class struct A : virtual simple::A { - // VTABLE-EXTENDED-A: VFTable for 'V1' in 'simple::A' in 'extended::A' (2 entries). - // VTABLE-EXTENDED-A-NEXT: 0 | void simple::A::f() - // VTABLE-EXTENDED-A-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, - // VTABLE-EXTENDED-A-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] - // VTABLE-EXTENDED-A-NEXT: 1 | extended::A::~A() [scalar deleting] - // VTABLE-EXTENDED-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' (2 entries). + // CHECK-NEXT: 0 | void simple::A::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] + // CHECK-NEXT: 1 | extended::A::~A() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] // `vtordispex{8,8,4294967292,8}' // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ" @@ -168,28 +256,38 @@ struct A : virtual simple::A { }; A a; +void use(A *obj) { delete obj; } struct B : virtual simple::A { // This class has an implicit dtor. Vdtors don't require vtordispex thunks // as the most derived class always has an implicit dtor, // which is a final overrider. - // VTABLE-EXTENDED-B: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries). + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries). // ... - // VTABLE-EXTENDED-B: 1 | extended::B::~B() [scalar deleting] - // VTABLE-EXTENDED-B-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK: 1 | extended::B::~B() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] // vtordisp{4294967292,0} // MANGLING-DAG: @"\01??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z" }; B b; +void use(B *obj) { delete obj; } struct C : virtual simple::A { - // VTABLE-EXTENDED-C: VFTable for 'V1' in 'simple::A' in 'extended::C' (2 entries). - // VTABLE-EXTENDED-C-NEXT: 0 | void simple::A::f() - // VTABLE-EXTENDED-C-NEXT: [this adjustment: vtordisp at -4, vbptr at 12 to the left, - // VTABLE-EXTENDED-C-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::C' (2 entries). + // CHECK-NEXT: 0 | void simple::A::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 12 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 12 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] // `vtordispex{12,8,4294967292,8}' // MANGLING-DAG: @"\01?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ" @@ -199,6 +297,7 @@ struct C : virtual simple::A { }; C c; +void use(C *obj) { delete obj; } struct D : virtual V2 { virtual void f(); @@ -207,10 +306,14 @@ struct D : virtual V2 { }; struct E : virtual D { - // VTABLE-EXTENDED-E: VFTable for 'V2' in 'extended::D' in 'extended::E' (2 entries). - // VTABLE-EXTENDED-E-NEXT: 0 | void extended::D::f() - // VTABLE-EXTENDED-E-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, - // VTABLE-EXTENDED-E-NEXT: vboffset at 8 in the vbtable, 12 non-virtual] + // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::E' (2 entries). + // CHECK-NEXT: 0 | void extended::D::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual] + + // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual] // `vtordispex{8,8,4294967292,12}' // MANGLING-DAG: @"\01?f@D@extended@@$R477PPPPPPPM@M@AEXXZ" @@ -220,12 +323,17 @@ struct E : virtual D { }; E e; +void use(E *obj) { delete obj; } struct F : virtual Z, virtual D { - // VTABLE-EXTENDED-F: VFTable for 'V2' in 'extended::D' in 'extended::F' (2 entries). - // VTABLE-EXTENDED-F-NEXT: 0 | void extended::D::f() - // VTABLE-EXTENDED-F-NEXT: [this adjustment: vtordisp at -4, vbptr at 20 to the left, - // VTABLE-EXTENDED-F-NEXT: vboffset at 12 in the vbtable, 12 non-virtual] + // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::F' (2 entries). + // CHECK-NEXT: 0 | void extended::D::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 20 to the left, + // CHECK-NEXT: vboffset at 12 in the vbtable, 12 non-virtual] + + // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 20 to the left, + // CHECK-NEXT: vboffset at 12 in the vbtable, 12 non-virtual] // `vtordispex{20,12,4294967292,12}' // MANGLING-DAG: @"\01?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ" @@ -235,17 +343,22 @@ struct F : virtual Z, virtual D { }; F f; +void use(F *obj) { delete obj; } struct G : virtual simple::A { - // VTABLE-EXTENDED-G: VFTable for 'extended::G' (1 entries). - // VTABLE-EXTENDED-G-NEXT: 0 | void extended::G::g() + // CHECK-LABEL: VFTable for 'extended::G' (1 entry). + // CHECK-NEXT: 0 | void extended::G::g() + + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::G' (2 entries). + // CHECK-NEXT: 0 | void simple::A::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] + // CHECK-NEXT: 1 | extended::G::~G() [scalar deleting] + // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] - // VTABLE-EXTENDED-G: VFTable for 'V1' in 'simple::A' in 'extended::G' (2 entries). - // VTABLE-EXTENDED-G-NEXT: 0 | void simple::A::f() - // VTABLE-EXTENDED-G-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, - // VTABLE-EXTENDED-G-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] - // VTABLE-EXTENDED-G-NEXT: 1 | extended::G::~G() [scalar deleting] - // VTABLE-EXTENDED-G-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] // Emits a G's own vfptr, thus moving the vbptr in the layout. virtual void g(); @@ -256,22 +369,28 @@ struct G : virtual simple::A { }; G g; +void use(G *obj) { obj->g(); } struct H : Z, A { - // VTABLE-EXTENDED-H: VFTable for 'Z' in 'extended::H' (2 entries). - // VTABLE-EXTENDED-H-NEXT: 0 | void Z::g() - // VTABLE-EXTENDED-H-NEXT: 1 | extended::H::~H() [scalar deleting] + // CHECK-LABEL: VFTable for 'Z' in 'extended::H' (2 entries). + // CHECK-NEXT: 0 | void Z::g() + // CHECK-NEXT: 1 | extended::H::~H() [scalar deleting] + + // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries). + // CHECK-NEXT: 0 | void simple::A::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] - // VTABLE-EXTENDED-H: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries). - // VTABLE-EXTENDED-H-NEXT: 0 | void simple::A::f() - // VTABLE-EXTENDED-H-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, - // VTABLE-EXTENDED-H-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] + // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ" // MANGLING-DAG: @"\01??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z" }; H h; +void use(H *obj) { delete obj; } } namespace pr17738 { @@ -279,10 +398,14 @@ namespace pr17738 { // Just do the right thing. struct A : virtual simple::B { - // VTABLE-PR17738-A: VFTable for 'V2' in 'V3' in 'simple::B' in 'pr17738::A' (2 entries). - // VTABLE-PR17738-A-NEXT: 0 | void simple::B::f() - // VTABLE-PR17738-A-NEXT: [this adjustment: vtordisp at -12, vbptr at 20 to the left, - // VTABLE-PR17738-A-NEXT: vboffset at 8 in the vbtable, 16 non-virtual] + // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'pr17738::A' (2 entries). + // CHECK-NEXT: 0 | void simple::B::f() + // CHECK-NEXT: [this adjustment: vtordisp at -12, vbptr at 20 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual] + + // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, vbptr at 20 to the left, + // CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual] // MANGLING-DAG: @"\01?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ" int a; @@ -290,6 +413,41 @@ struct A : virtual simple::B { }; A a; +void use(A *obj) { delete obj; } +} + +namespace pr19408 { +// In this test, the vptr used to vcall D::f() is located in the A vbase. +// The offset of A in different in C and D, so the D vtordisp thunk should +// adjust "this" so C::f gets the right value. +struct A { + A(); + virtual void f(); + int a; +}; + +struct B : virtual A { + B(); + int b; +}; + +struct C : B { + C(); + virtual void f(); + int c; +}; + +struct D : C { + // CHECK-LABEL: VFTable for 'pr19408::A' in 'pr19408::B' in 'pr19408::C' in 'pr19408::D' (1 entry). + // CHECK-NEXT: 0 | void pr19408::C::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual] + + // MANGLING-DAG: @"\01?f@C@pr19408@@$4PPPPPPPM@3AEXXZ" + D(); + int d; +}; + +D::D() {} } namespace access { @@ -322,3 +480,90 @@ struct C : virtual B { C c; } + +namespace pr19505 { +struct A { + virtual void f(); + virtual void z(); +}; + +struct B : A { + virtual void f(); +}; + +struct C : A, B { + virtual void g(); +}; + +struct X : B, virtual C { + X() {} + virtual void g(); + + // CHECK-LABEL: VFTable for 'pr19505::A' in 'pr19505::B' in 'pr19505::C' in 'pr19505::X' (2 entries). + // CHECK-NEXT: 0 | void pr19505::B::f() + // CHECK-NEXT: 1 | void pr19505::A::z() + + // MANGLING-DAG: @"\01??_7X@pr19505@@6BB@1@@" = {{.*}}@"\01?f@B@pr19505@@UAEXXZ" +} x; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace pr19506 { +struct A { + virtual void f(); + virtual void g(); +}; + +struct B : A { + virtual void f(); +}; + +struct C : B {}; + +struct X : C, virtual B { + virtual void g(); + X() {} + + // CHECK-LABEL: VFTable for 'pr19506::A' in 'pr19506::B' in 'pr19506::X' (2 entries). + // CHECK-NEXT: 0 | void pr19506::B::f() + // CHECK-NEXT: 1 | void pr19506::X::g() + // CHECK-NEXT: [this adjustment: vtordisp at -4, -12 non-virtual] + + // MANGLING-DAG: @"\01??_7X@pr19506@@6BB@1@@" = {{.*}}@"\01?f@B@pr19506@@UAEXXZ" +} x; + +void build_vftable(X *obj) { obj->g(); } +} + +namespace pr19519 { +// VS2013 CL miscompiles this, just make sure we don't regress. + +struct A { + virtual void f(); + virtual void g(); +}; + +struct B : virtual A { + virtual void f(); + B(); +}; + +struct C : virtual A { + virtual void g(); +}; + +struct X : B, C { + X(); + + // CHECK-LABEL: VFTable for 'pr19519::A' in 'pr19519::B' in 'pr19519::X' (2 entries). + // CHECK-NEXT: 0 | void pr19519::B::f() + // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual] + // CHECK-NEXT: 1 | void pr19519::C::g() + // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual] + + // MANGLING-DAG: @"\01??_7X@pr19519@@6B@" = {{.*}}@"\01?g@C@pr19519@@$4PPPPPPPM@3AEXXZ" +}; + +X::X() {} +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index b58a0b14cdcda..4ce4e9c2e17ee 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -1,29 +1,5 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -cxx-abi microsoft -triple=i386-pc-win32 >%t - -// RUN: FileCheck --check-prefix=VTABLE-C %s < %t -// RUN: FileCheck --check-prefix=VTABLE-D %s < %t -// RUN: FileCheck --check-prefix=TEST1 %s < %t -// RUN: FileCheck --check-prefix=TEST2 %s < %t -// RUN: FileCheck --check-prefix=TEST3 %s < %t -// RUN: FileCheck --check-prefix=TEST4 %s < %t -// RUN: FileCheck --check-prefix=TEST5 %s < %t -// RUN: FileCheck --check-prefix=TEST6 %s < %t -// RUN: FileCheck --check-prefix=TEST7 %s < %t -// RUN: FileCheck --check-prefix=TEST8-X %s < %t -// RUN: FileCheck --check-prefix=TEST8-Z %s < %t -// RUN: FileCheck --check-prefix=TEST9-Y %s < %t -// RUN: FileCheck --check-prefix=TEST9-Z %s < %t -// RUN: FileCheck --check-prefix=TEST9-W %s < %t -// RUN: FileCheck --check-prefix=TEST9-T %s < %t -// RUN: FileCheck --check-prefix=TEST10 %s < %t -// RUN: FileCheck --check-prefix=VDTORS-Y %s < %t -// RUN: FileCheck --check-prefix=VDTORS-U %s < %t -// RUN: FileCheck --check-prefix=VDTORS-V %s < %t -// RUN: FileCheck --check-prefix=VDTORS-P %s < %t -// RUN: FileCheck --check-prefix=RET-W %s < %t -// RUN: FileCheck --check-prefix=RET-T %s < %t -// RUN: FileCheck --check-prefix=RET-V %s < %t - +// RUN: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t +// RUN: FileCheck %s < %t // RUN: FileCheck --check-prefix=MANGLING %s < %t.ll struct Empty { }; @@ -38,34 +14,35 @@ struct B { }; struct C: virtual A { - // VTABLE-C: VFTable for 'A' in 'C' (2 entries) - // VTABLE-C-NEXT: 0 | void C::f() - // VTABLE-C-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries) + // CHECK-NEXT: 0 | void C::f() + // CHECK-NEXT: 1 | void A::z() - // VTABLE-C: VFTable indices for 'C' (1 entries) - // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0 - // VTABLE-C-NEXT: 0 | void C::f() + // CHECK-LABEL: VFTable indices for 'C' (1 entry) + // CHECK-NEXT: vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void C::f() // MANGLING-DAG: @"\01??_7C@@6B@" - virtual void f(); + virtual void f() {} }; C c; +void use(C *obj) { obj->f(); } struct D: virtual A { - // VTABLE-D: VFTable for 'D' (1 entries). - // VTABLE-D-NEXT: 0 | void D::h() + // CHECK-LABEL: VFTable for 'D' (1 entry). + // CHECK-NEXT: 0 | void D::h() - // VTABLE-D: VFTable for 'A' in 'D' (2 entries). - // VTABLE-D-NEXT: 0 | void D::f() - // VTABLE-D-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'D' (2 entries). + // CHECK-NEXT: 0 | void D::f() + // CHECK-NEXT: 1 | void A::z() - // VTABLE-D: VFTable indices for 'D' (2 entries). - // VTABLE-D-NEXT: via vfptr at offset 0 - // VTABLE-D-NEXT: 0 | void D::h() - // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0 - // VTABLE-D-NEXT: 0 | void D::f() + // CHECK-LABEL: VFTable indices for 'D' (2 entries). + // CHECK-NEXT: via vfptr at offset 0 + // CHECK-NEXT: 0 | void D::h() + // CHECK-NEXT: via vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void D::f() // MANGLING-DAG: @"\01??_7D@@6B0@@" // MANGLING-DAG: @"\01??_7D@@6BA@@@" @@ -74,8 +51,8 @@ struct D: virtual A { virtual void h(); }; -void D::h() {} D d; +void use(D *obj) { obj->h(); } namespace Test1 { @@ -86,33 +63,34 @@ struct Y : X, A { }; // MANGLING-DAG: @"\01??_7Y@Test1@@6B@" struct Z : virtual Y { - // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries). - // TEST1-NEXT: 0 | void A::f() - // TEST1-NEXT: 1 | void A::z() + Z(); + // CHECK-LABEL: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST1-NOT: VFTable indices for 'Test1::Z' + // CHECK-NOT: VFTable indices for 'Test1::Z' // MANGLING-DAG: @"\01??_7Z@Test1@@6B@" }; -Z z; +Z::Z() {} } namespace Test2 { struct X: virtual A, virtual B { - // TEST2: VFTable for 'Test2::X' (1 entries). - // TEST2-NEXT: 0 | void Test2::X::h() + // CHECK-LABEL: VFTable for 'Test2::X' (1 entry). + // CHECK-NEXT: 0 | void Test2::X::h() - // TEST2: VFTable for 'A' in 'Test2::X' (2 entries). - // TEST2-NEXT: 0 | void A::f() - // TEST2-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'Test2::X' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST2: VFTable for 'B' in 'Test2::X' (1 entries). - // TEST2-NEXT: 0 | void B::g() + // CHECK-LABEL: VFTable for 'B' in 'Test2::X' (1 entry). + // CHECK-NEXT: 0 | void B::g() - // TEST2: VFTable indices for 'Test2::X' (1 entries). - // TEST2-NEXT: 0 | void Test2::X::h() + // CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry). + // CHECK-NEXT: 0 | void Test2::X::h() // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@" // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@" @@ -122,6 +100,7 @@ struct X: virtual A, virtual B { }; X x; +void use(X *obj) { obj->h(); } } namespace Test3 { @@ -131,40 +110,45 @@ struct X : virtual A { }; struct Y: virtual X { - // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries). - // TEST3-NEXT: 0 | void A::f() - // TEST3-NEXT: 1 | void A::z() + Y(); + // CHECK-LABEL: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST3-NOT: VFTable indices for 'Test3::Y' + // CHECK-NOT: VFTable indices for 'Test3::Y' // MANGLING-DAG: @"\01??_7Y@Test3@@6B@" }; -Y y; +Y::Y() {} } namespace Test4 { struct X: virtual C { + X(); // This one's interesting. C::f expects (A*) to be passed as 'this' and does // ECX-=4 to cast to (C*). In X, C and A vbases are reordered, so the thunk // should pass a pointer to the end of X in order // for ECX-=4 to point at the C part. - // TEST4: VFTable for 'A' in 'C' in 'Test4::X' (2 entries). - // TEST4-NEXT: 0 | void C::f() - // TEST4-NEXT: [this adjustment: 8 non-virtual] - // TEST4-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test4::X' (2 entries). + // CHECK-NEXT: 0 | void C::f() + // CHECK-NEXT: [this adjustment: 8 non-virtual] + // CHECK-NEXT: 1 | void A::z() + + // CHECK-LABEL: Thunks for 'void C::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual] - // TEST4-NOT: VFTable indices for 'Test4::X' + // CHECK-NOT: VFTable indices for 'Test4::X' // MANGLING-DAG: @"\01??_7X@Test4@@6B@" // Also check the mangling of the thunk. - // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ" + // MANGLING-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ" }; -X x; +X::X() {} } namespace Test5 { @@ -176,16 +160,16 @@ struct X : A { }; struct Y : virtual X { - // TEST5: VFTable for 'Test5::Y' (1 entries). - // TEST5-NEXT: 0 | void Test5::Y::h() + // CHECK-LABEL: VFTable for 'Test5::Y' (1 entry). + // CHECK-NEXT: 0 | void Test5::Y::h() - // TEST5: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries). - // TEST5-NEXT: 0 | void A::f() - // TEST5-NEXT: 1 | void A::z() - // TEST5-NEXT: 2 | void Test5::X::g() + // CHECK-LABEL: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() + // CHECK-NEXT: 2 | void Test5::X::g() - // TEST5: VFTable indices for 'Test5::Y' (1 entries). - // TEST5-NEXT: 0 | void Test5::Y::h() + // CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry). + // CHECK-NEXT: 0 | void Test5::Y::h() // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@" // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@" @@ -194,21 +178,23 @@ struct Y : virtual X { }; Y y; +void use(Y *obj) { obj->h(); } } namespace Test6 { struct X : A, virtual Empty { - // TEST6: VFTable for 'A' in 'Test6::X' (2 entries). - // TEST6-NEXT: 0 | void A::f() - // TEST6-NEXT: 1 | void A::z() + X(); + // CHECK-LABEL: VFTable for 'A' in 'Test6::X' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST6-NOT: VFTable indices for 'Test6::X' + // CHECK-NOT: VFTable indices for 'Test6::X' // MANGLING-DAG: @"\01??_7X@Test6@@6B@" }; -X x; +X::X() {} } namespace Test7 { @@ -218,36 +204,37 @@ struct X : C { }; struct Y : virtual X { - // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries). - // TEST7-NEXT: 0 | void C::f() - // TEST7-NEXT: [this adjustment: 8 non-virtual] - // TEST7-NEXT: 1 | void A::z() + Y(); + // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries). + // CHECK-NEXT: 0 | void C::f() + // CHECK-NEXT: [this adjustment: 8 non-virtual] + // CHECK-NEXT: 1 | void A::z() - // TEST7: Thunks for 'void C::f()' (1 entry). - // TEST7-NEXT: 0 | [this adjustment: 8 non-virtual] + // CHECK-LABEL: Thunks for 'void C::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual] - // TEST7-NOT: VFTable indices for 'Test7::Y' + // CHECK-NOT: VFTable indices for 'Test7::Y' // MANGLING-DAG: @"\01??_7Y@Test7@@6B@" }; -Y y; +Y::Y() {} } namespace Test8 { // This is a typical diamond inheritance with a shared 'A' vbase. struct X : D, C { - // TEST8-X: VFTable for 'D' in 'Test8::X' (1 entries). - // TEST8-X-NEXT: 0 | void D::h() + // CHECK-LABEL: VFTable for 'D' in 'Test8::X' (1 entry). + // CHECK-NEXT: 0 | void D::h() - // TEST8-X: VFTable for 'A' in 'D' in 'Test8::X' (2 entries). - // TEST8-X-NEXT: 0 | void Test8::X::f() - // TEST8-X-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test8::X' (2 entries). + // CHECK-NEXT: 0 | void Test8::X::f() + // CHECK-NEXT: 1 | void A::z() - // TEST8-X: VFTable indices for 'Test8::X' (1 entries). - // TEST8-X-NEXT: via vbtable index 1, vfptr at offset 0 - // TEST8-X-NEXT: 0 | void Test8::X::f() + // CHECK-LABEL: VFTable indices for 'Test8::X' (1 entry). + // CHECK-NEXT: via vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void Test8::X::f() // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@" // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@" @@ -256,21 +243,45 @@ struct X : D, C { }; X x; +void use(X *obj) { obj->f(); } // Another diamond inheritance which led to AST crashes. struct Y : virtual A {}; -class Z : Y, C { - // TEST8-Z: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries). - // TEST8-Z-NEXT: 0 | void Test8::Z::f() - // TEST8-Z-NEXT: 1 | void A::z() +struct Z : Y, C { + // CHECK-LABEL: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries). + // CHECK-NEXT: 0 | void Test8::Z::f() + // CHECK-NEXT: 1 | void A::z() - // TEST8-Z: VFTable indices for 'Test8::Z' (1 entries). - // TEST8-Z-NEXT: via vbtable index 1, vfptr at offset 0 - // TEST8-Z-NEXT: 0 | void Test8::Z::f() + // CHECK-LABEL: VFTable indices for 'Test8::Z' (1 entry). + // CHECK-NEXT: via vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void Test8::Z::f() virtual void f(); }; Z z; +void use(Z *obj) { obj->f(); } + +// Another diamond inheritance which we miscompiled (PR18967). +struct W : virtual A { + virtual void bar(); +}; + +struct T : W, C { + // CHECK-LABEL: VFTable for 'Test8::W' in 'Test8::T' (1 entry) + // CHECK-NEXT: 0 | void Test8::T::bar() + + // CHECK-LABEL: VFTable for 'A' in 'Test8::W' in 'Test8::T' (2 entries) + // CHECK-NEXT: 0 | void C::f() + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void A::z() + + // CHECK-LABEL: Thunks for 'void C::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] + virtual void bar(); + int field; +}; +T t; +void use(T *obj) { obj->bar(); } } namespace Test9 { @@ -278,15 +289,15 @@ namespace Test9 { struct X : A { }; struct Y : virtual X { - // TEST9-Y: VFTable for 'Test9::Y' (1 entries). - // TEST9-Y-NEXT: 0 | void Test9::Y::h() + // CHECK-LABEL: VFTable for 'Test9::Y' (1 entry). + // CHECK-NEXT: 0 | void Test9::Y::h() - // TEST9-Y: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries). - // TEST9-Y-NEXT: 0 | void A::f() - // TEST9-Y-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries). - // TEST9-Y-NEXT: 0 | void Test9::Y::h() + // CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry). + // CHECK-NEXT: 0 | void Test9::Y::h() // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@" // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@" @@ -295,115 +306,110 @@ struct Y : virtual X { }; Y y; +void use(Y *obj) { obj->h(); } struct Z : Y, virtual B { - // TEST9-Z: VFTable for 'Test9::Y' in 'Test9::Z' (1 entries). - // TEST9-Z-NEXT: 0 | void Test9::Y::h() + Z(); + // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' (1 entry). + // CHECK-NEXT: 0 | void Test9::Y::h() - // TEST9-Z: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries). - // TEST9-Z-NEXT: 0 | void A::f() - // TEST9-Z-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST9-Z: VFTable for 'B' in 'Test9::Z' (1 entries). - // TEST9-Z-NEXT: 0 | void B::g() + // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' (1 entry). + // CHECK-NEXT: 0 | void B::g() - // TEST9-Z-NOT: VFTable indices for 'Test9::Z' + // CHECK-NOT: VFTable indices for 'Test9::Z' // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@" // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@" - // FIXME this one is wrong: - // INCORRECT MANGLING-DAG: @"\01??_7Z@Test9@@6BB@@@" - // MANGLING-DAG-SHOULD-BE: @"\01??_7Z@Test9@@6B@" + // MANGLING-DAG: @"\01??_7Z@Test9@@6B@" }; -Z z; +Z::Z() {} struct W : Z, D, virtual A, virtual B { - // TEST9-W: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entries). - // TEST9-W-NEXT: 0 | void Test9::Y::h() + W(); + // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entry). + // CHECK-NEXT: 0 | void Test9::Y::h() - // TEST9-W: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries). - // TEST9-W-NEXT: 0 | void A::f() - // TEST9-W-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries). + // CHECK-NEXT: 0 | void A::f() + // CHECK-NEXT: 1 | void A::z() - // TEST9-W: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entries). - // TEST9-W-NEXT: 0 | void B::g() + // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entry). + // CHECK-NEXT: 0 | void B::g() - // TEST9-W: VFTable for 'D' in 'Test9::W' (1 entries). - // TEST9-W-NEXT: 0 | void D::h() + // CHECK-LABEL: VFTable for 'D' in 'Test9::W' (1 entry). + // CHECK-NEXT: 0 | void D::h() - // TEST9-W: VFTable for 'A' in 'D' in 'Test9::W' (2 entries). - // TEST9-W-NEXT: 0 | void D::f() - // TEST9-W-NEXT: [this adjustment: -8 non-virtual] - // TEST9-W-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::W' (2 entries). + // CHECK-NEXT: 0 | void D::f() + // CHECK-NEXT: [this adjustment: -8 non-virtual] + // CHECK-NEXT: 1 | void A::z() - // TEST9-W: Thunks for 'void D::f()' (1 entry). - // TEST9-W-NEXT: 0 | [this adjustment: -8 non-virtual] + // CHECK-LABEL: Thunks for 'void D::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] - // TEST9-W-NOT: VFTable indices for 'Test9::W' + // CHECK-NOT: VFTable indices for 'Test9::W' // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@" // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@" // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@" - // FIXME: these two are wrong: - // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BB@@@" - // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6B@" - // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@Z@1@@" - // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6BY@1@@" + // MANGLING-DAG: @"\01??_7W@Test9@@6B@" + // MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@@" }; -W w; +W::W() {} struct T : Z, D, virtual A, virtual B { - // TEST9-T: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entries). - // TEST9-T-NEXT: 0 | void Test9::T::h() + // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entry). + // CHECK-NEXT: 0 | void Test9::T::h() - // TEST9-T: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries). - // TEST9-T-NEXT: 0 | void Test9::T::f() - // TEST9-T-NEXT: 1 | void Test9::T::z() + // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries). + // CHECK-NEXT: 0 | void Test9::T::f() + // CHECK-NEXT: 1 | void Test9::T::z() - // TEST9-T: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entries). - // TEST9-T-NEXT: 0 | void Test9::T::g() + // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entry). + // CHECK-NEXT: 0 | void Test9::T::g() - // TEST9-T: VFTable for 'D' in 'Test9::T' (1 entries). - // TEST9-T-NEXT: 0 | void Test9::T::h() - // TEST9-T-NEXT: [this adjustment: -8 non-virtual] + // CHECK-LABEL: VFTable for 'D' in 'Test9::T' (1 entry). + // CHECK-NEXT: 0 | void Test9::T::h() + // CHECK-NEXT: [this adjustment: -8 non-virtual] - // TEST9-T: Thunks for 'void Test9::T::h()' (1 entry). - // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual] + // CHECK-LABEL: Thunks for 'void Test9::T::h()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] - // TEST9-T: VFTable for 'A' in 'D' in 'Test9::T' (2 entries). - // TEST9-T-NEXT: 0 | void Test9::T::f() - // TEST9-T-NEXT: [this adjustment: -8 non-virtual] - // TEST9-T-NEXT: 1 | void Test9::T::z() - // TEST9-T-NEXT: [this adjustment: -8 non-virtual] + // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::T' (2 entries). + // CHECK-NEXT: 0 | void Test9::T::f() + // CHECK-NEXT: [this adjustment: -8 non-virtual] + // CHECK-NEXT: 1 | void Test9::T::z() + // CHECK-NEXT: [this adjustment: -8 non-virtual] - // TEST9-T: Thunks for 'void Test9::T::f()' (1 entry). - // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual] + // CHECK-LABEL: Thunks for 'void Test9::T::f()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] - // TEST9-T: Thunks for 'void Test9::T::z()' (1 entry). - // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual] + // CHECK-LABEL: Thunks for 'void Test9::T::z()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] - // TEST9-T: VFTable indices for 'Test9::T' (4 entries). - // TEST9-T-NEXT: via vfptr at offset 0 - // TEST9-T-NEXT: 0 | void Test9::T::h() - // TEST9-T-NEXT: via vbtable index 1, vfptr at offset 0 - // TEST9-T-NEXT: 0 | void Test9::T::f() - // TEST9-T-NEXT: 1 | void Test9::T::z() - // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0 - // TEST9-T-NEXT: 0 | void Test9::T::g() + // CHECK-LABEL: VFTable indices for 'Test9::T' (4 entries). + // CHECK-NEXT: via vfptr at offset 0 + // CHECK-NEXT: 0 | void Test9::T::h() + // CHECK-NEXT: via vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void Test9::T::f() + // CHECK-NEXT: 1 | void Test9::T::z() + // CHECK-NEXT: via vbtable index 2, vfptr at offset 0 + // CHECK-NEXT: 0 | void Test9::T::g() // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@" // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@" // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@" - // FIXME: these two are wrong: - // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BB@@@" - // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6B@" - // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@Z@1@@" - // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6BY@1@@" + // MANGLING-DAG: @"\01??_7T@Test9@@6B@" + // MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@@" virtual void f(); virtual void g(); @@ -412,22 +418,70 @@ struct T : Z, D, virtual A, virtual B { }; T t; +void use(T *obj) { obj->f(); } } namespace Test10 { struct X : virtual C, virtual A { - // TEST10: VFTable for 'A' in 'C' in 'Test10::X' (2 entries). - // TEST10-NEXT: 0 | void Test10::X::f() - // TEST10-NEXT: 1 | void A::z() + // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test10::X' (2 entries). + // CHECK-NEXT: 0 | void Test10::X::f() + // CHECK-NEXT: 1 | void A::z() - // TEST10: VFTable indices for 'Test10::X' (1 entries). - // TEST10-NEXT: via vbtable index 1, vfptr at offset 0 - // TEST10-NEXT: 0 | void Test10::X::f() + // CHECK-LABEL: VFTable indices for 'Test10::X' (1 entry). + // CHECK-NEXT: via vbtable index 1, vfptr at offset 0 + // CHECK-NEXT: 0 | void Test10::X::f() virtual void f(); }; void X::f() {} X x; +void use(X *obj) { obj->f(); } +} + +namespace Test11 { +struct X : virtual A {}; +struct Y { virtual void g(); }; + +struct Z : virtual X, Y { + // MANGLING-DAG: @"\01??_7Z@Test11@@6BY@1@@" + // MANGLING-DAG: @"\01??_7Z@Test11@@6BX@1@@" +}; + +Z z; + +struct W : virtual X, A {}; + +// Used to crash, PR17748. +W w; +} + +namespace Test12 { +struct X : B, A { }; + +struct Y : X { + virtual void f(); // Overrides A::f. +}; + +struct Z : virtual Y { + // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' (2 entries). + // CHECK-NEXT: 0 | void Test12::Y::f() + // CHECK-NEXT: 1 | void A::z() + + int z; + // MANGLING-DAG: @"\01??_7Z@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ" +}; + +struct W : Z { + // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' in 'Test12::W' (2 entries). + // CHECK-NEXT: 0 | void Test12::Y::f() + // CHECK-NEXT: 1 | void A::z() + W(); + + int w; + // MANGLING-DAG: @"\01??_7W@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ" +}; + +W::W() {} } namespace vdtors { @@ -437,15 +491,16 @@ struct X { }; struct Y : virtual X { - // VDTORS-Y: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries). - // VDTORS-Y-NEXT: 0 | vdtors::Y::~Y() [scalar deleting] - // VDTORS-Y-NEXT: 1 | void vdtors::X::zzz() + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries). + // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting] + // CHECK-NEXT: 1 | void vdtors::X::zzz() - // VDTORS-Y-NOT: Thunks for 'vdtors::Y::~Y()' + // CHECK-NOT: Thunks for 'vdtors::Y::~Y()' virtual ~Y(); }; Y y; +void use(Y *obj) { delete obj; } struct Z { virtual void z(); @@ -456,59 +511,86 @@ struct W : Z, X { }; struct U : virtual W { - // VDTORS-U: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entries). - // VDTORS-U-NEXT: 0 | void vdtors::Z::z() + // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entry). + // CHECK-NEXT: 0 | void vdtors::Z::z() - // VDTORS-U: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries). - // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting] - // VDTORS-U-NEXT: [this adjustment: -4 non-virtual] - // VDTORS-U-NEXT: 1 | void vdtors::X::zzz() + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries). + // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void vdtors::X::zzz() - // VDTORS-U: Thunks for 'vdtors::W::~W()' (1 entry). - // VDTORS-U-NEXT: 0 | [this adjustment: -4 non-virtual] + // CHECK-LABEL: Thunks for 'vdtors::U::~U()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] - // VDTORS-U: VFTable indices for 'vdtors::U' (1 entries). - // VDTORS-U-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- - // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting] + // CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry). + // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- + // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting] virtual ~U(); }; U u; +void use(U *obj) { delete obj; } struct V : virtual W { - // VDTORS-V: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entries). - // VDTORS-V-NEXT: 0 | void vdtors::Z::z() + // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entry). + // CHECK-NEXT: 0 | void vdtors::Z::z() - // VDTORS-V: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries). - // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting] - // VDTORS-V-NEXT: [this adjustment: -4 non-virtual] - // VDTORS-V-NEXT: 1 | void vdtors::X::zzz() + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries). + // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void vdtors::X::zzz() - // VDTORS-V: Thunks for 'vdtors::W::~W()' (1 entry). - // VDTORS-V-NEXT: 0 | [this adjustment: -4 non-virtual] + // CHECK-LABEL: Thunks for 'vdtors::V::~V()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] - // VDTORS-V: VFTable indices for 'vdtors::V' (1 entries). - // VDTORS-V-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- - // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting] + // CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry). + // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- + // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting] }; V v; +void use(V *obj) { delete obj; } struct T : virtual X { virtual ~T(); }; struct P : T, Y { - // VDTORS-P: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries). - // VDTORS-P-NEXT: 0 | vdtors::P::~P() [scalar deleting] - // VDTORS-P-NEXT: 1 | void vdtors::X::zzz() + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries). + // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting] + // CHECK-NEXT: 1 | void vdtors::X::zzz() - // VDTORS-P-NOT: Thunks for 'vdtors::P::~P()' + // CHECK-NOT: Thunks for 'vdtors::P::~P()' virtual ~P(); }; P p; +void use(P *obj) { delete obj; } + +struct Q { + virtual ~Q(); +}; + +// PR19172: Yet another diamond we miscompiled. +struct R : virtual Q, X { + // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry). + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] + // CHECK-NEXT: [this adjustment: -8 non-virtual] + // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry). + // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] + + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries). + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] + // CHECK-NEXT: 1 | void vdtors::X::zzz() + + // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry). + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] + virtual ~R(); +}; + +R r; +void use(R *obj) { delete obj; } } namespace return_adjustment { @@ -526,50 +608,159 @@ struct Z { }; struct W : Z { - // RET-W: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries). - // RET-W-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo() - // RET-W-NEXT: [return adjustment: vbase #1, 0 non-virtual] - // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo() + // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries). + // CHECK-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo() + // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual] + // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo() + + // CHECK-LABEL: Thunks for 'return_adjustment::X *return_adjustment::W::foo()' (1 entry). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual] - // RET-W: VFTable indices for 'return_adjustment::W' (1 entries). - // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo() + // CHECK-LABEL: VFTable indices for 'return_adjustment::W' (1 entry). + // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo() virtual X* foo(); }; -W y; +W w; +void use(W *obj) { obj->foo(); } struct T : W { - // RET-T: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries). - // RET-T-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo() - // RET-T-NEXT: [return adjustment: vbase #1, 0 non-virtual] - // RET-T-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo() - // RET-T-NEXT: [return adjustment: vbase #2, 0 non-virtual] - // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo() + // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries). + // CHECK-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo() + // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual] + // CHECK-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo() + // CHECK-NEXT: [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual] + // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo() + + // CHECK-LABEL: Thunks for 'return_adjustment::Y *return_adjustment::T::foo()' (2 entries). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual] + // CHECK-NEXT: 1 | [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual] - // RET-T: VFTable indices for 'return_adjustment::T' (1 entries). - // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo() + // CHECK-LABEL: VFTable indices for 'return_adjustment::T' (1 entry). + // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo() virtual Y* foo(); }; T t; +void use(T *obj) { obj->foo(); } struct U : virtual A { virtual void g(); // adds a vfptr }; struct V : Z { - // RET-V: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries). - // RET-V-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo() - // RET-V-NEXT: [return adjustment: vbptr at offset 4, vbase #1, 0 non-virtual] - // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo() + // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries). + // CHECK-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo() + // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual] + // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo() + + // CHECK-LABEL: Thunks for 'return_adjustment::U *return_adjustment::V::foo()' (1 entry). + // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual] - // RET-V: VFTable indices for 'return_adjustment::V' (1 entries). - // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo() + // CHECK-LABEL: VFTable indices for 'return_adjustment::V' (1 entry). + // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo() virtual U* foo(); }; V v; +void use(V *obj) { obj->foo(); } +} + +namespace pr17748 { +struct A { + virtual void f() {} +}; + +struct B : virtual A { + B() {} +}; + +struct C : virtual B, A { + C() {} +}; +C c; + +// MANGLING-DAG: @"\01??_7A@pr17748@@6B@" +// MANGLING-DAG: @"\01??_7B@pr17748@@6B@" +// MANGLING-DAG: @"\01??_7C@pr17748@@6BA@1@@" +// MANGLING-DAG: @"\01??_7C@pr17748@@6BB@1@@" +} + +namespace pr19066 { +struct X : virtual B {}; + +struct Y : virtual X, B { + Y(); + // CHECK-LABEL: VFTable for 'B' in 'pr19066::X' in 'pr19066::Y' (1 entry). + // CHECK-NEXT: 0 | void B::g() + + // CHECK-LABEL: VFTable for 'B' in 'pr19066::Y' (1 entry). + // CHECK-NEXT: 0 | void B::g() +}; + +Y::Y() {} +} + +namespace pr19240 { +struct A { + virtual void c(); +}; + +struct B : virtual A { + virtual void c(); +}; + +struct C { }; + +struct D : virtual A, virtual C, B {}; + +D obj; + +// Each MDC only has one vftable. + +// MANGLING-DAG: @"\01??_7D@pr19240@@6B@" +// MANGLING-DAG: @"\01??_7A@pr19240@@6B@" +// MANGLING-DAG: @"\01??_7B@pr19240@@6B@" + +} + +namespace pr19408 { +// This test is a non-vtordisp version of the reproducer for PR19408. +struct X : virtual A { + int x; +}; + +struct Y : X { + virtual void f(); + int y; +}; + +struct Z : Y { + // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::Z' (2 entries). + // CHECK-NEXT: 0 | void pr19408::Y::f() + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void A::z() + + Z(); + int z; + // MANGLING-DAG: @"\01??_7Z@pr19408@@6B@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ" +}; + +Z::Z() {} + +struct W : B, Y { + // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::W' (2 entries). + // CHECK-NEXT: 0 | void pr19408::Y::f() + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | void A::z() + + W(); + int w; + // MANGLING-DAG: @"\01??_7W@pr19408@@6BY@1@@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ" +}; + +W::W() {} } diff --git a/test/CodeGenCXX/microsoft-compatibility.cpp b/test/CodeGenCXX/microsoft-compatibility.cpp new file mode 100644 index 0000000000000..297184a1df2a4 --- /dev/null +++ b/test/CodeGenCXX/microsoft-compatibility.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -fms-compatibility -emit-llvm -o - | FileCheck %s + +template<class T> +void destroy(T *p) { + p->~T(); +} + +extern "C" void f() { + int a; + destroy((void*)&a); +} + +// CHECK-LABEL: define void @f() +// CHECK: call void @"\01??$destroy@X@@YAXPAX@Z" +// CHECK: ret void + +// CHECK-LABEL: define linkonce_odr void @"\01??$destroy@X@@YAXPAX@Z"(i8* %p) +// The pseudo-dtor expr should not generate calls to anything. +// CHECK-NOT: call +// CHECK-NOT: invoke +// CHECK: ret void diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp index 419075a863032..c030d1d0b3b5a 100644 --- a/test/CodeGenCXX/microsoft-interface.cpp +++ b/test/CodeGenCXX/microsoft-interface.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-win32 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-windows-gnu -emit-llvm %s -o - | FileCheck %s __interface I { int test() { @@ -20,24 +20,21 @@ int fn() { // CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)] // CHECK-LABEL: define i32 @_Z2fnv() -// CHECK: call void @_ZN1SC1Ev(%struct.S* %s) -// CHECK: %{{[.0-9A-Z_a-z]+}} = call i32 @_ZN1S4testEv(%struct.S* %s) +// CHECK: call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s) +// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %s) -// CHECK-LABEL: define linkonce_odr void @_ZN1SC1Ev(%struct.S* %this) -// CHECK: call void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}}) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this) +// CHECK: call x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}}) -// CHECK-LABEL: define linkonce_odr i32 @_ZN1S4testEv(%struct.S* %this) -// CHECK: %{{[.0-9A-Z_a-z]+}} = call i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}}) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this) +// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}}) -// CHECK-LABEL: define linkonce_odr i32 @_ZN1I4testEv(%__interface.I* %this) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this) // CHECK: ret i32 1 -// CHECK-LABEL: define linkonce_odr void @_ZN1SC2Ev(%struct.S* %this) -// CHECK: call void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}}) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this) +// CHECK: call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}}) // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}} -// CHECK-LABEL: define linkonce_odr void @_ZN1IC2Ev(%__interface.I* %this) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this) // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}} - -// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSERKS_(%__interface.I* %this, %__interface.I*) -// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSEOS_(%__interface.I* %this, %__interface.I*) diff --git a/test/CodeGenCXX/microsoft-new.cpp b/test/CodeGenCXX/microsoft-new.cpp index 48e93d4aa0f88..7857e478ef82b 100644 --- a/test/CodeGenCXX/microsoft-new.cpp +++ b/test/CodeGenCXX/microsoft-new.cpp @@ -1,39 +1,39 @@ -// RUN: %clang_cc1 -triple i686-pc-win32 -fms-compatibility %s -emit-llvm -o - | FileCheck %s
-
-#include <stddef.h>
-
-struct arbitrary_t {} arbitrary;
-void *operator new(size_t size, arbitrary_t);
-
-struct arbitrary2_t {} arbitrary2;
-void *operator new[](size_t size, arbitrary2_t);
-
-namespace PR13164 {
- void f() {
- // MSVC will fall back on the non-array operator new.
- void *a;
- int *p = new(arbitrary) int[4];
- // CHECK: call i8* @_Znwj11arbitrary_t(i32 16, %struct.arbitrary_t*
- }
-
- struct S {
- void *operator new[](size_t size, arbitrary_t);
- };
-
- void g() {
- S *s = new(arbitrary) S[2];
- // CHECK: call i8* @_ZN7PR131641SnaEj11arbitrary_t(i32 2, %struct.arbitrary_t*
- S *s1 = new(arbitrary) S;
- // CHECK: call i8* @_Znwj11arbitrary_t(i32 1, %struct.arbitrary_t*
- }
-
- struct T {
- void *operator new(size_t size, arbitrary2_t);
- };
-
- void h() {
- // This should still call the global operator new[].
- T *t = new(arbitrary2) T[2];
- // CHECK: call i8* @_Znaj12arbitrary2_t(i32 2, %struct.arbitrary2_t*
- }
-}
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-compatibility %s -emit-llvm -o - | FileCheck %s + +#include <stddef.h> + +struct arbitrary_t {} arbitrary; +void *operator new(size_t size, arbitrary_t); + +struct arbitrary2_t {} arbitrary2; +void *operator new[](size_t size, arbitrary2_t); + +namespace PR13164 { + void f() { + // MSVC will fall back on the non-array operator new. + void *a; + int *p = new(arbitrary) int[4]; + // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 16, %struct.arbitrary_t* + } + + struct S { + void *operator new[](size_t size, arbitrary_t); + }; + + void g() { + S *s = new(arbitrary) S[2]; + // CHECK: call i8* @"\01??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t* + S *s1 = new(arbitrary) S; + // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(i32 1, %struct.arbitrary_t* + } + + struct T { + void *operator new(size_t size, arbitrary2_t); + }; + + void h() { + // This should still call the global operator new[]. + T *t = new(arbitrary2) T[2]; + // CHECK: call i8* @"\01??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t* + } +} diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp new file mode 100644 index 0000000000000..d4002c28b1a20 --- /dev/null +++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -fno-rtti-data -triple=i386-pc-win32 -o - -emit-llvm | FileCheck %s + +// vftable shouldn't have RTTI data in it. +// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] + +struct type_info; +namespace std { using ::type_info; } + +struct S { + virtual ~S(); +} s; + +struct U : S { + virtual ~U(); +}; + +extern S *getS(); + +const std::type_info &ti = typeid(*getS()); +const U &u = dynamic_cast<U &>(*getS()); +// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"\01??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"\01??_R0?AUU@@@8" to i8*), i32 1) diff --git a/test/CodeGenCXX/microsoft-templ-uuidof.cpp b/test/CodeGenCXX/microsoft-templ-uuidof.cpp new file mode 100644 index 0000000000000..0ee3908638378 --- /dev/null +++ b/test/CodeGenCXX/microsoft-templ-uuidof.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK + +struct _GUID; + +template <typename> +struct X { +}; + +struct __declspec(uuid("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}")) A {}; + +struct B {}; + +template <> +struct __declspec(uuid("{BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB}")) X<B> {}; + +struct __declspec(uuid("{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}")) C {}; + +const _GUID &xa = __uuidof(X<A>); +// CHECK-DAG: @"\01?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa + +const _GUID &xb = __uuidof(X<B>); +// CHECK-DAG: @"\01?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb +const _GUID &xc = __uuidof(X<C>); +// CHECK-DAG: @"\01?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc + +template <> +struct __declspec(uuid("{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}")) X<C> {}; + +template <typename> +struct __declspec(uuid("{EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE}")) Y { +}; + +const _GUID &xd = __uuidof(X<C>); +// CHECK-DAG: @"\01?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd + +const _GUID &yd = __uuidof(Y<X<C> >); +// CHECK-DAG: @"\01?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp index ab3d9b64c6f8b..d57ca8380e39f 100644 --- a/test/CodeGenCXX/microsoft-uuidof.cpp +++ b/test/CodeGenCXX/microsoft-uuidof.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s -// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID +// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID #ifdef DEFINE_GUID struct _GUID { diff --git a/test/CodeGenCXX/mingw-new-abi.cpp b/test/CodeGenCXX/mingw-new-abi.cpp new file mode 100644 index 0000000000000..2b05253b0985a --- /dev/null +++ b/test/CodeGenCXX/mingw-new-abi.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-pc-mingw32 %s -o - | FileCheck --check-prefix=MINGW %s +// RUN: %clang_cc1 -emit-llvm -triple i386-pc-cygwin %s -o - | FileCheck --check-prefix=CYGWIN %s + +namespace test1 { + struct foo { + // MINGW: declare x86_thiscallcc void @_ZN5test13foo1fEv + // CYGWIN: declare void @_ZN5test13foo1fEv + void f(); + }; + void g(foo *x) { + x->f(); + } +} diff --git a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp new file mode 100644 index 0000000000000..92e704a0a3090 --- /dev/null +++ b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips-unknown-linux-gnu < %s | FileCheck --check-prefix=O32 %s +// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips64-unknown-linux-gnu -target-abi n32 < %s | FileCheck --check-prefix=N32 %s +// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips64-unknown-linux-gnu -target-abi n64 < %s | FileCheck --check-prefix=N64 %s + +// Test that the size_t is correct for the ABI. It's not sufficient to be the +// correct size, it must be the same type for correct name mangling. + +long *alloc_long() { + long *rv = new long; // size_t is implicit in the new operator + return rv; +} +// O32-LABEL: define i32* @_Z10alloc_longv() +// O32: call noalias i8* @_Znwj(i32 4) + +// N32-LABEL: define i32* @_Z10alloc_longv() +// N32: call noalias i8* @_Znwj(i32 4) + +// N64-LABEL: define i64* @_Z10alloc_longv() +// N64: call noalias i8* @_Znwm(i64 8) + +long *alloc_long_array() { + long *rv = new long[2]; + return rv; +} + +// O32-LABEL: define i32* @_Z16alloc_long_arrayv() +// O32: call noalias i8* @_Znaj(i32 8) + +// N32-LABEL: define i32* @_Z16alloc_long_arrayv() +// N32: call noalias i8* @_Znaj(i32 8) + +// N64-LABEL: define i64* @_Z16alloc_long_arrayv() +// N64: call noalias i8* @_Znam(i64 16) + +#include <stddef.h> + +void size_t_arg(size_t a) { +} + +// O32-LABEL: _Z10size_t_argj +// N32-LABEL: _Z10size_t_argj +// N64-LABEL: _Z10size_t_argm + +void ptrdiff_t_arg(ptrdiff_t a) { +} + +// O32-LABEL: _Z13ptrdiff_t_argi +// N32-LABEL: _Z13ptrdiff_t_argi +// N64-LABEL: _Z13ptrdiff_t_argl diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp new file mode 100644 index 0000000000000..3f868f36ff661 --- /dev/null +++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s + +enum Enum { zero, one, two }; + +struct __declspec(dllexport) S { + // In MS compatibility mode, this counts as a definition. + // Since it is exported, it must be emitted even if it's unreferenced. + static const short x = 42; + + // This works for enums too. + static const Enum y = two; + + struct NonExported { + // dllexport is not inherited by this nested class. + // Since z is not referenced, it should not be emitted. + static const int z = 42; + }; +}; + +// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, align 2 +// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, align 4 +// CHECK-NOT: NonExported diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp index 00beaa62f1902..b02b679d71a13 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s -// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE -// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE -// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE +// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s +// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-INLINE +// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE +// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-INLINE struct S { // For MS ABI, we emit a linkonce_odr definition here, even though it's really just a declaration. diff --git a/test/CodeGenCXX/ms_wide_predefined_expr.cpp b/test/CodeGenCXX/ms_wide_predefined_expr.cpp index 5f0bcdee8c053..3949d39ad52f6 100644 --- a/test/CodeGenCXX/ms_wide_predefined_expr.cpp +++ b/test/CodeGenCXX/ms_wide_predefined_expr.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -fms-extensions -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s -// CHECK: @L__FUNCTION__._Z4funcv = private constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], align 2 +// CHECK: @"\01??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], align 2 void wprint(const wchar_t*); diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp index 0e925c0a67ebf..65123ea7feefe 100644 --- a/test/CodeGenCXX/new-array-init.cpp +++ b/test/CodeGenCXX/new-array-init.cpp @@ -6,8 +6,8 @@ void fn(int n) { // CHECK: store i32 1 // CHECK: store i32 2 // CHECK: store i32 3 - // CHECK: icmp eq i32* - // CHECK-NEXT: br i1 + // CHECK: sub {{.*}}, 12 + // CHECK: call void @llvm.memset new int[n] { 1, 2, 3 }; } @@ -31,3 +31,18 @@ void const_sufficient() { new int[4] { 1, 2, 3 }; // CHECK: ret void } + +// CHECK-LABEL: define void @_Z22check_array_value_initv +void check_array_value_init() { + struct S; + new (int S::*[3][4][5]) (); + + // CHECK: call noalias i8* @_Zna{{.}}(i{{32 240|64 480}}) + // CHECK: getelementptr inbounds i{{32|64}}* {{.*}}, i{{32|64}} 60 + + // CHECK: phi + // CHECK: store i{{32|64}} -1, + // CHECK: getelementptr inbounds i{{32|64}}* {{.*}}, i{{32|64}} 1 + // CHECK: icmp eq + // CHECK: br i1 +} diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 91da77a0838a9..862161b193857 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -2,6 +2,9 @@ typedef __typeof__(sizeof(0)) size_t; +// Declare an 'operator new' template to tickle a bug in __builtin_operator_new. +template<typename T> void *operator new(size_t, int (*)(T)); + // Ensure that this declaration doesn't cause operator new to lose its // 'noalias' attribute. void *operator new[](size_t); @@ -33,7 +36,6 @@ void *operator new[](size_t, const std::nothrow_t &) throw(); void operator delete(void *, const std::nothrow_t &) throw(); void operator delete[](void *, const std::nothrow_t &) throw(); - void t2(int* a) { int* b = new (a) int; } @@ -285,7 +287,7 @@ void *operator new(size_t, MyPlacementType); namespace N3664 { struct S { S() throw(int); }; - // CHECK-LABEL-LABEL: define void @_ZN5N36641fEv + // CHECK-LABEL: define void @_ZN5N36641fEv void f() { // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] int *p = new int; @@ -307,7 +309,7 @@ namespace N3664 { // FIXME: Can we mark this noalias? // CHECK: declare i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]] - // CHECK-LABEL-LABEL: define void @_ZN5N36641gEv + // CHECK-LABEL: define void @_ZN5N36641gEv void g() { // It's OK for there to be attributes here, so long as we don't have a // 'builtin' attribute. @@ -326,6 +328,15 @@ namespace N3664 { } } +namespace builtins { + // CHECK-LABEL: define void @_ZN8builtins1fEv + void f() { + // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]] + // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]] + __builtin_operator_delete(__builtin_operator_new(4)); + } +} + // CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}} // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} diff --git a/test/CodeGenCXX/no-elide-constructors.cpp b/test/CodeGenCXX/no-elide-constructors.cpp new file mode 100644 index 0000000000000..ecb350f43ec95 --- /dev/null +++ b/test/CodeGenCXX/no-elide-constructors.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98 +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11 +// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98-ELIDE +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11-ELIDE + +// Reduced from PR12208 +class X { +public: + X(); + X(const X&); +#if __cplusplus >= 201103L + X(X&&); +#endif + ~X(); +}; + +// CHECK-LABEL: define void @_Z4Testv( +X Test() +{ + X x; + + // Check that the copy constructor for X is called with result variable as + // sret argument. + // CHECK-CXX98: call void @_ZN1XC1ERKS_( + // CHECK-CXX11: call void @_ZN1XC1EOS_( + // CHECK-CXX98-ELIDE-NOT: call void @_ZN1XC1ERKS_( + // CHECK-CXX11-ELIDE-NOT: call void @_ZN1XC1EOS_( + + // Make sure that the destructor for X is called. + // FIXME: This call is present even in the -ELIDE runs, but is guarded by a + // branch that is never taken in those cases. We could generate better IR + // here. + // CHECK: call void @_ZN1XD1Ev( + return x; +} diff --git a/test/CodeGenCXX/noinline-template.cpp b/test/CodeGenCXX/noinline-template.cpp index 51a84f74a650b..3dd4366f73e35 100644 --- a/test/CodeGenCXX/noinline-template.cpp +++ b/test/CodeGenCXX/noinline-template.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // This was a problem in Sema, but only shows up as noinline missing // in CodeGen. -// CHECK: define linkonce_odr void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) [[NI:#[0-9]+]] +// CHECK: define linkonce_odr {{.*}}void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) [[NI:#[0-9]+]] template <class Ty> struct Vector { void growStorageBy(); diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index b83dd727e0bb8..aad287dc3206c 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -9,6 +9,14 @@ public: ~X(); }; +template<typename T> struct Y { + Y(); + static Y f() { + Y y; + return y; + } +}; + // CHECK-LABEL: define void @_Z5test0v // CHECK-EH-LABEL: define void @_Z5test0v X test0() { @@ -108,12 +116,17 @@ X test2(bool B) { } +// CHECK-LABEL: define void @_Z5test3b X test3(bool B) { - // FIXME: We don't manage to apply NRVO here, although we could. - { + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ + // CHECK: call {{.*}} @_ZN1XC1Ev + // CHECK: call {{.*}} @_ZN1XC1ERKS_ + if (B) { X y; return y; } + // FIXME: we should NRVO this variable too. X x; return x; } @@ -156,9 +169,40 @@ X test6() { return a; // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8 // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]]) - // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]]) + // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* dereferenceable({{[0-9]+}}) [[A]]) // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]]) // CHECK-NEXT: ret void } +// CHECK-LABEL: define void @_Z5test7b +X test7(bool b) { + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NEXT: ret + if (b) { + X x; + return x; + } + return X(); +} + +// CHECK-LABEL: define void @_Z5test8b +X test8(bool b) { + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NEXT: ret + if (b) { + X x; + return x; + } else { + X y; + return y; + } +} + +Y<int> test9() { + Y<int>::f(); +} + +// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv +// CHECK: tail call {{.*}} @_ZN1YIiEC1Ev + // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp index 5c79568c2ace0..31d774c5345e1 100644 --- a/test/CodeGenCXX/pod-member-memcpys.cpp +++ b/test/CodeGenCXX/pod-member-memcpys.cpp @@ -108,59 +108,59 @@ CALL_AO(InnerClassMember) CALL_AO(PackedMembers) // Basic copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret %struct.Basic* // PODMember copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret %struct.PODMember* // PODLikeMember copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret %struct.PODLikeMember* // ArrayMember copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}}) // CHECK: ret %struct.ArrayMember* // VolatileMember copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: load volatile i32* {{.*}}, align 4 // CHECK: store volatile i32 {{.*}}, align 4 -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret %struct.VolatileMember* // BitfieldMember copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}}) // CHECK: ret %struct.BitfieldMember* // InnerClass copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*) +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret %struct.InnerClassMember* // PackedMembers copy-assignment: -// CHECK-LABEL: define linkonce_odr %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*) -// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_ +// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}})) +// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}}) // CHECK: ret %struct.PackedMembers* @@ -184,21 +184,21 @@ CALL_CC(PODMember) CALL_CC(Basic) // Basic copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic*) +// CHECK-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret void // PODMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret void // PODLikeMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) // CHECK: invoke void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) @@ -207,14 +207,14 @@ CALL_CC(Basic) // CHECK: invoke void @_ZN7PODLikeD1Ev // ArrayMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}}) // CHECK: ret void // VolatileMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: load volatile i32* {{.*}}, align 4 // CHECK: store volatile i32 {{.*}}, align 4 @@ -223,34 +223,34 @@ CALL_CC(Basic) // CHECK: ret void // BitfieldMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}}) // CHECK: ret void // InnerClass copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}}) // CHECK: ret void // ReferenceMember copy-constructor: -// CHECK-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember*) +// CHECK-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember* dereferenceable({{[0-9]+}})) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}}) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}}) // CHECK: ret void // BitfieldMember2 copy-constructor: -// CHECK-2-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2*) +// CHECK-2-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2* dereferenceable({{[0-9]+}})) // CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false) // CHECK-2: call void @_ZN6NonPODC1ERKS_ // CHECK-2: ret void // PackedMembers copy-assignment: -// CHECK-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*) +// CHECK-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}})) // CHECK: call void @_ZN6NonPODC1ERKS_ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}}) // CHECK: ret void diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index f0199c851dcd1..745cf18fce216 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -202,7 +202,7 @@ namespace BoolPtrToMember { bool member; }; - // CHECK-LABEL: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b + // CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b bool &f(X &x, bool X::*member) { // CHECK: {{bitcast.* to i8\*}} // CHECK-NEXT: getelementptr inbounds i8* diff --git a/test/CodeGenCXX/poly-unsigned.cpp b/test/CodeGenCXX/poly-unsigned.cpp new file mode 100644 index 0000000000000..e2ab430a969ed --- /dev/null +++ b/test/CodeGenCXX/poly-unsigned.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -target-feature +neon -ffreestanding -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-UNSIGNED-POLY %s +// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -ffreestanding -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-UNSIGNED-POLY %s +// RUN: %clang_cc1 -triple armv7-apple-ios -ffreestanding -target-cpu cortex-a8 -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-SIGNED-POLY %s + +#include <arm_neon.h> + +// Polynomial types really should be universally unsigned, otherwise casting +// (say) poly8_t "x^7" to poly16_t would change it to "x^15 + x^14 + ... + +// x^7". Unfortunately 32-bit ARM ended up in a slightly delicate ABI situation +// so for now it got that wrong. + +poly16_t test_poly8(poly8_t pIn) { +// CHECK-UNSIGNED-POLY: @_Z10test_poly8h +// CHECK-UNSIGNED-POLY: zext i8 {{.*}} to i16 + +// CHECK-SIGNED-POLY: @_Z10test_poly8a +// CHECK-SIGNED-POLY: sext i8 {{.*}} to i16 + + return pIn; +} diff --git a/test/CodeGenCXX/pr11797.cpp b/test/CodeGenCXX/pr11797.cpp index 1098372ce3894..2a31090e42187 100644 --- a/test/CodeGenCXX/pr11797.cpp +++ b/test/CodeGenCXX/pr11797.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fvisibility hidden -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -fvisibility hidden -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s namespace std __attribute__ ((__visibility__ ("default"))) {} #pragma GCC visibility push(default) diff --git a/test/CodeGenCXX/pr12104.cpp b/test/CodeGenCXX/pr12104.cpp index a62f04b66834a..560ffbe5b35c8 100644 --- a/test/CodeGenCXX/pr12104.cpp +++ b/test/CodeGenCXX/pr12104.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -include %S/pr12104.h %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -x c++ -emit-pch -o %t %S/pr12104.h -// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -include %S/pr12104.h %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -emit-pch -o %t %S/pr12104.h +// RUN: %clang_cc1 -include-pch %t %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s template struct Patch<1>; diff --git a/test/CodeGenCXX/pr13396.cpp b/test/CodeGenCXX/pr13396.cpp index 3d582c51006b4..e41dd39fcc6e7 100644 --- a/test/CodeGenCXX/pr13396.cpp +++ b/test/CodeGenCXX/pr13396.cpp @@ -7,13 +7,13 @@ struct foo { }; foo::foo() { - // CHECK-LABEL: define void @_ZN3fooC1Ev(%struct.foo* inreg %this) // CHECK-LABEL: define void @_ZN3fooC2Ev(%struct.foo* inreg %this) + // CHECK-LABEL: define void @_ZN3fooC1Ev(%struct.foo* inreg %this) } foo::~foo() { - // CHECK-LABEL: define void @_ZN3fooD1Ev(%struct.foo* inreg %this) // CHECK-LABEL: define void @_ZN3fooD2Ev(%struct.foo* inreg %this) + // CHECK-LABEL: define void @_ZN3fooD1Ev(%struct.foo* inreg %this) } void dummy() { diff --git a/test/CodeGenCXX/pr18661.cpp b/test/CodeGenCXX/pr18661.cpp new file mode 100644 index 0000000000000..235867831e28e --- /dev/null +++ b/test/CodeGenCXX/pr18661.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fcxx-exceptions -fms-extensions -emit-llvm -o - | FileCheck %s + +extern "C" { + void f(); + + // In MS mode we don't validate the exception specification. + void f() throw() { + } +} + +// PR18661: Clang would fail to emit function definition with mismatching +// exception specification, even though it was just treated as a warning. + +// CHECK: define void @f() diff --git a/test/CodeGenCXX/pr18962.cpp b/test/CodeGenCXX/pr18962.cpp new file mode 100644 index 0000000000000..ab537b4928e37 --- /dev/null +++ b/test/CodeGenCXX/pr18962.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple i686-linux-gnu %s -emit-llvm -o - | FileCheck %s + +class A { + // append has to have the same prototype as fn1 to tickle the bug. + void (*append)(A *); +}; + +class B {}; +class D; + +// C has to be non-C++98 POD with available tail padding, making the LLVM base +// type differ from the complete LLVM type. +class C { + // This member creates a circular LLVM type reference to %class.D. + D *m_group; + B changeListeners; +}; +class D : C {}; + +void fn1(A *p1) { +} + +void +fn2(C *) { +} + +// We end up using an opaque type for 'append' to avoid circular references. +// CHECK: %class.A = type { {}* } +// CHECK: %class.C = type { %class.D*, %class.B } +// CHECK: %class.D = type { %class.C.base, [3 x i8] } +// CHECK: %class.C.base = type <{ %class.D*, %class.B }> +// CHECK: %class.B = type { i8 } diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp index c2d54e19215d7..46fd60914b0ef 100644 --- a/test/CodeGenCXX/pr9965.cpp +++ b/test/CodeGenCXX/pr9965.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s struct A { A(); }; template<typename T> struct X : A // default constructor is not trivial diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp new file mode 100644 index 0000000000000..3f9ff217e6b66 --- /dev/null +++ b/test/CodeGenCXX/pragma-init_seg.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s + +int f(); + +// CHECK: $"\01?x@selectany_init@@3HA" = comdat any +// CHECK: $"\01?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any +// CHECK: $"\01?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any + +namespace simple_init { +#pragma init_seg(compiler) +int x = f(); +// CHECK: @"\01?x@simple_init@@3HA" = global i32 0, align 4 +// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"\01??__Ex@simple_init@@YAXXZ", section ".CRT$XCC" + +#pragma init_seg(lib) +int y = f(); +// CHECK: @"\01?y@simple_init@@3HA" = global i32 0, align 4 +// CHECK: @__cxx_init_fn_ptr1 = private constant void ()* @"\01??__Ey@simple_init@@YAXXZ", section ".CRT$XCL" + +#pragma init_seg(user) +int z = f(); +// CHECK: @"\01?z@simple_init@@3HA" = global i32 0, align 4 +// No function pointer! This one goes on @llvm.global_ctors. +} + +#pragma init_seg(".asdf") + +namespace internal_init { +namespace { +int x = f(); +// CHECK: @"\01?x@?A@internal_init@@3HA" = internal global i32 0, align 4 +// CHECK: @__cxx_init_fn_ptr2 = private constant void ()* @"\01??__Ex@?A@internal_init@@YAXXZ", section ".asdf" +} +} + +namespace selectany_init { +int __declspec(selectany) x = f(); +// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr global i32 0, comdat $"\01?x@selectany_init@@3HA", align 4 +// CHECK: @__cxx_init_fn_ptr3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat $"\01?x@selectany_init@@3HA" +} + +namespace explicit_template_instantiation { +template <typename T> struct A { static const int x; }; +template <typename T> const int A<T>::x = f(); +template struct A<int>; +// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr global i32 0, comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB", align 4 +// CHECK: @__cxx_init_fn_ptr4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB" +} + +namespace implicit_template_instantiation { +template <typename T> struct A { static const int x; }; +template <typename T> const int A<T>::x = f(); +int g() { return A<int>::x; } +// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr global i32 0, comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB", align 4 +// CHECK: @__cxx_init_fn_ptr5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB" +} + +// ... and here's where we emitted user level ctors. +// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] +// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_pragma_init_seg.cpp, i8* null }] + +// We have to mark everything used so we can survive globalopt, even through +// LTO. There's no way LLVM could really understand if data in the .asdf +// section is really used or dead. +// +// CHECK: @llvm.used = appending global [6 x i8*] +// CHECK: [i8* bitcast (void ()** @__cxx_init_fn_ptr to i8*), +// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr1 to i8*), +// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr2 to i8*), +// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr3 to i8*), +// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr4 to i8*), +// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr5 to i8*)], section "llvm.metadata" diff --git a/test/CodeGenCXX/pragma-pack-3.cpp b/test/CodeGenCXX/pragma-pack-3.cpp new file mode 100644 index 0000000000000..49509a5b2a8ee --- /dev/null +++ b/test/CodeGenCXX/pragma-pack-3.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -triple=i686-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct Base { + char a; +}; + +struct Derived_1 : virtual Base +{ + char b; +}; + +#pragma pack(1) +struct Derived_2 : Derived_1 { + // CHECK: %struct.Derived_2 = type { %struct.Derived_1.base, %struct.Base } + // CHECK: %struct.Derived_1.base = type <{ i32 (...)**, i8 }> +}; + +Derived_2 x; diff --git a/test/CodeGenCXX/pragma-weak.cpp b/test/CodeGenCXX/pragma-weak.cpp index c033079140405..e2d464818edb0 100644 --- a/test/CodeGenCXX/pragma-weak.cpp +++ b/test/CodeGenCXX/pragma-weak.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s #pragma weak zex int zex; @@ -10,7 +10,7 @@ int zex; #pragma weak foo struct S { void foo(); }; void S::foo() {} -// CHECK-LABEL: define void @_ZN1S3fooEv( +// CHECK-LABEL: define {{.*}}void @_ZN1S3fooEv( #pragma weak zed namespace bar { void zed() {} } diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp index 9062ee095c3a4..f901467c4f4b4 100644 --- a/test/CodeGenCXX/predefined-expr.cpp +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s // CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00" // CHECK: private unnamed_addr constant [26 x i8] c"void NS::externFunction()\00" @@ -10,7 +10,7 @@ // CHECK: private unnamed_addr constant [122 x i8] c"static void ClassWithTemplateTemplateParam<char, NS::ClassTemplate>::staticMember() [T = char, Param = NS::ClassTemplate]\00" // CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00" // CHECK: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00" -// CHECK: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::<anonymous class>::operator()() const\00" +// CHECK: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::(anonymous class)::operator()() const\00" // CHECK: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00" // CHECK: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00" @@ -28,13 +28,13 @@ // CHECK: private unnamed_addr constant [46 x i8] c"void NS::Base::functionTemplate1(T) [T = int]\00" // CHECK: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00" -// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous union>::anonymousUnionFunction()\00" +// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous union)::anonymousUnionFunction()\00" // CHECK: private unnamed_addr constant [24 x i8] c"anonymousStructFunction\00" -// CHECK: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous struct>::anonymousStructFunction()\00" +// CHECK: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous struct)::anonymousStructFunction()\00" // CHECK: private unnamed_addr constant [23 x i8] c"anonymousClassFunction\00" -// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous class>::anonymousClassFunction()\00" +// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous class)::anonymousClassFunction()\00" // CHECK: private unnamed_addr constant [12 x i8] c"~Destructor\00" // CHECK: private unnamed_addr constant [30 x i8] c"NS::Destructor::~Destructor()\00" @@ -93,7 +93,7 @@ // CHECK: private unnamed_addr constant [59 x i8] c"void ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" // CHECK: private unnamed_addr constant [27 x i8] c"anonymousNamespaceFunction\00" -// CHECK: private unnamed_addr constant [84 x i8] c"void <anonymous namespace>::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00" +// CHECK: private unnamed_addr constant [84 x i8] c"void (anonymous namespace)::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00" // CHECK: private unnamed_addr constant [19 x i8] c"localClassFunction\00" // CHECK: private unnamed_addr constant [59 x i8] c"void NS::localClass(int)::LocalClass::localClassFunction()\00" diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp index 914a90a4be1ad..e02b2096be99c 100644 --- a/test/CodeGenCXX/ptr-to-member-function.cpp +++ b/test/CodeGenCXX/ptr-to-member-function.cpp @@ -1,8 +1,7 @@ -// REQUIRES: x86-registered-target,x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck -check-prefix CHECK-LP64 %s +// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \ +// RUN: FileCheck -check-prefix CHECK-LP32 %s // 13.3.3.2 Ranking implicit conversion sequences extern "C" int printf(...); @@ -64,8 +63,8 @@ int main() B1 c = B1(2); } -// CHECK-LP64: callq __ZN1XcvM1BFvvEEv -// CHECK-LP64: callq __Z1gM1CFvvE +// CHECK-LP64: call { i64, i64 } @_ZN1XcvM1BFvvEEv +// CHECK-LP64: call void @_Z1gM1CFvvE -// CHECK-LP32: calll L__ZN1XcvM1BFvvEEv -// CHECK-LP32: calll __Z1gM1CFvvE +// CHECK-LP32: call i64 @_ZN1XcvM1BFvvEEv +// CHECK-LP32: call void @_Z1gM1CFvvE diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp index 60ea393af96c7..c4be5b78c2e4d 100644 --- a/test/CodeGenCXX/reference-cast.cpp +++ b/test/CodeGenCXX/reference-cast.cpp @@ -3,7 +3,7 @@ // PR6024 extern int i; -// CHECK: define i32* @_Z16lvalue_noop_castv() [[NUW:#[0-9]+]] +// CHECK: define dereferenceable({{[0-9]+}}) i32* @_Z16lvalue_noop_castv() [[NUW:#[0-9]+]] const int &lvalue_noop_cast() { if (i == 0) // CHECK: store i32 17, i32* @@ -15,7 +15,7 @@ const int &lvalue_noop_cast() { return 17; } -// CHECK-LABEL: define i16* @_Z20lvalue_integral_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i16* @_Z20lvalue_integral_castv() const short &lvalue_integral_cast() { if (i == 0) // CHECK: store i16 17, i16* @@ -27,7 +27,7 @@ const short &lvalue_integral_cast() { return 17; } -// CHECK-LABEL: define i16* @_Z29lvalue_floating_integral_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i16* @_Z29lvalue_floating_integral_castv() const short &lvalue_floating_integral_cast() { if (i == 0) // CHECK: store i16 17, i16* @@ -39,7 +39,7 @@ const short &lvalue_floating_integral_cast() { return 17.5; } -// CHECK-LABEL: define float* @_Z29lvalue_integral_floating_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) float* @_Z29lvalue_integral_floating_castv() const float &lvalue_integral_floating_cast() { if (i == 0) // CHECK: store float 1.700000e+{{0*}}1, float* @@ -51,7 +51,7 @@ const float &lvalue_integral_floating_cast() { return 17; } -// CHECK-LABEL: define float* @_Z20lvalue_floating_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) float* @_Z20lvalue_floating_castv() const float &lvalue_floating_cast() { if (i == 0) // CHECK: store float 1.700000e+{{0*}}1, float* @@ -65,7 +65,7 @@ const float &lvalue_floating_cast() { int get_int(); -// CHECK-LABEL: define i8* @_Z24lvalue_integer_bool_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_Z24lvalue_integer_bool_castv() const bool &lvalue_integer_bool_cast() { if (i == 0) // CHECK: call i32 @_Z7get_intv() @@ -82,7 +82,7 @@ const bool &lvalue_integer_bool_cast() { float get_float(); -// CHECK-LABEL: define i8* @_Z25lvalue_floating_bool_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_Z25lvalue_floating_bool_castv() const bool &lvalue_floating_bool_cast() { if (i == 0) // CHECK: call float @_Z9get_floatv() @@ -107,7 +107,7 @@ typedef int (X::*pmf)(int); pm get_pointer_to_member_data(); pmf get_pointer_to_member_function(); -// CHECK-LABEL: define i8* @_Z26lvalue_ptrmem_to_bool_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_Z26lvalue_ptrmem_to_bool_castv() const bool &lvalue_ptrmem_to_bool_cast() { if (i == 0) // CHECK: call i64 @_Z26get_pointer_to_member_datav() @@ -125,7 +125,7 @@ const bool &lvalue_ptrmem_to_bool_cast() { return get_pointer_to_member_data(); } -// CHECK-LABEL: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_Z27lvalue_ptrmem_to_bool_cast2v const bool &lvalue_ptrmem_to_bool_cast2() { if (i == 0) // CHECK: {{call.*_Z30get_pointer_to_member_functionv}} diff --git a/test/CodeGenCXX/reference-field.cpp b/test/CodeGenCXX/reference-field.cpp index 0312029259520..54e914d0f3fce 100644 --- a/test/CodeGenCXX/reference-field.cpp +++ b/test/CodeGenCXX/reference-field.cpp @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s -O2 | grep "@_Z1bv" +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s -O2 | FileCheck %s // Make sure the call to b() doesn't get optimized out. extern struct x {char& x,y;}y; int b(); int a() { if (!&y.x) b(); } + +// CHECK: @_Z1bv diff --git a/test/CodeGenCXX/reference-init.cpp b/test/CodeGenCXX/reference-init.cpp index d47b1f37489c7..3a3eaeee78f6b 100644 --- a/test/CodeGenCXX/reference-init.cpp +++ b/test/CodeGenCXX/reference-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -verify %s +// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -verify %s // expected-no-diagnostics struct XPTParamDescriptor {}; diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index ec7a3d5daa8f6..454c306a13a7d 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -241,7 +241,7 @@ struct A { }; // CHECK-LABEL: define internal void @__cxx_global_var_init -// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E, i32 123) +// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E_, i32 123) // CHECK: call i32 @__cxa_atexit // CHECK: ret void const A &sA123 = A(123); @@ -256,7 +256,7 @@ struct A { void f() { // CHECK-LABEL: define void @_ZN2N41fEv - // CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar) + // CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar_) // CHECK: call i32 @__cxa_atexit // CHECK: ret void static const A& ar = A(); diff --git a/test/CodeGenCXX/return.cpp b/test/CodeGenCXX/return.cpp index 1975055fdb74e..5c1cfdaeed750 100644 --- a/test/CodeGenCXX/return.cpp +++ b/test/CodeGenCXX/return.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT // CHECK: @_Z9no_return // CHECK-OPT: @_Z9no_return diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp index 2495e969bff89..e70c3aa365976 100644 --- a/test/CodeGenCXX/rtti-fundamental.cpp +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -15,102 +15,107 @@ namespace __cxxabiv1 { } // void -// CHECK: @_ZTIv = unnamed_addr constant -// CHECK: @_ZTIPv = unnamed_addr constant -// CHECK: @_ZTIPKv = unnamed_addr constant +// CHECK: @_ZTIv = constant +// CHECK: @_ZTIPv = constant +// CHECK: @_ZTIPKv = constant // std::nullptr_t -// CHECK: @_ZTIDn = unnamed_addr constant -// CHECK: @_ZTIPDn = unnamed_addr constant -// CHECK: @_ZTIPKDn = unnamed_addr constant +// CHECK: @_ZTIDn = constant +// CHECK: @_ZTIPDn = constant +// CHECK: @_ZTIPKDn = constant // bool -// CHECK: @_ZTIb = unnamed_addr constant -// CHECK: @_ZTIPb = unnamed_addr constant -// CHECK: @_ZTIPKb = unnamed_addr constant +// CHECK: @_ZTIb = constant +// CHECK: @_ZTIPb = constant +// CHECK: @_ZTIPKb = constant // wchar_t -// CHECK: @_ZTIw = unnamed_addr constant -// CHECK: @_ZTIPw = unnamed_addr constant -// CHECK: @_ZTIPKw = unnamed_addr constant +// CHECK: @_ZTIw = constant +// CHECK: @_ZTIPw = constant +// CHECK: @_ZTIPKw = constant // char -// CHECK: @_ZTIc = unnamed_addr constant -// CHECK: @_ZTIPc = unnamed_addr constant -// CHECK: @_ZTIPKc = unnamed_addr constant +// CHECK: @_ZTIc = constant +// CHECK: @_ZTIPc = constant +// CHECK: @_ZTIPKc = constant // unsigned char -// CHECK: @_ZTIh = unnamed_addr constant -// CHECK: @_ZTIPh = unnamed_addr constant -// CHECK: @_ZTIPKh = unnamed_addr constant +// CHECK: @_ZTIh = constant +// CHECK: @_ZTIPh = constant +// CHECK: @_ZTIPKh = constant // signed char -// CHECK: @_ZTIa = unnamed_addr constant -// CHECK: @_ZTIPa = unnamed_addr constant -// CHECK: @_ZTIPKa = unnamed_addr constant +// CHECK: @_ZTIa = constant +// CHECK: @_ZTIPa = constant +// CHECK: @_ZTIPKa = constant // short -// CHECK: @_ZTIs = unnamed_addr constant -// CHECK: @_ZTIPs = unnamed_addr constant -// CHECK: @_ZTIPKs = unnamed_addr constant +// CHECK: @_ZTIs = constant +// CHECK: @_ZTIPs = constant +// CHECK: @_ZTIPKs = constant // unsigned short -// CHECK: @_ZTIt = unnamed_addr constant -// CHECK: @_ZTIPt = unnamed_addr constant -// CHECK: @_ZTIPKt = unnamed_addr constant +// CHECK: @_ZTIt = constant +// CHECK: @_ZTIPt = constant +// CHECK: @_ZTIPKt = constant // int -// CHECK: @_ZTIi = unnamed_addr constant -// CHECK: @_ZTIPi = unnamed_addr constant -// CHECK: @_ZTIPKi = unnamed_addr constant +// CHECK: @_ZTIi = constant +// CHECK: @_ZTIPi = constant +// CHECK: @_ZTIPKi = constant // unsigned int -// CHECK: @_ZTIj = unnamed_addr constant -// CHECK: @_ZTIPj = unnamed_addr constant -// CHECK: @_ZTIPKj = unnamed_addr constant +// CHECK: @_ZTIj = constant +// CHECK: @_ZTIPj = constant +// CHECK: @_ZTIPKj = constant // long -// CHECK: @_ZTIl = unnamed_addr constant -// CHECK: @_ZTIPl = unnamed_addr constant -// CHECK: @_ZTIPKl = unnamed_addr constant +// CHECK: @_ZTIl = constant +// CHECK: @_ZTIPl = constant +// CHECK: @_ZTIPKl = constant // unsigned long -// CHECK: @_ZTIm = unnamed_addr constant -// CHECK: @_ZTIPm = unnamed_addr constant -// CHECK: @_ZTIPKm = unnamed_addr constant +// CHECK: @_ZTIm = constant +// CHECK: @_ZTIPm = constant +// CHECK: @_ZTIPKm = constant // long long -// CHECK: @_ZTIx = unnamed_addr constant -// CHECK: @_ZTIPx = unnamed_addr constant -// CHECK: @_ZTIPKx = unnamed_addr constant +// CHECK: @_ZTIx = constant +// CHECK: @_ZTIPx = constant +// CHECK: @_ZTIPKx = constant // unsigned long long -// CHECK: @_ZTIy = unnamed_addr constant -// CHECK: @_ZTIPy = unnamed_addr constant -// CHECK: @_ZTIPKy = unnamed_addr constant +// CHECK: @_ZTIy = constant +// CHECK: @_ZTIPy = constant +// CHECK: @_ZTIPKy = constant + +// half +// CHECK: @_ZTIDh = constant +// CHECK: @_ZTIPDh = constant +// CHECK: @_ZTIPKDh = constant // float -// CHECK: @_ZTIf = unnamed_addr constant -// CHECK: @_ZTIPf = unnamed_addr constant -// CHECK: @_ZTIPKf = unnamed_addr constant +// CHECK: @_ZTIf = constant +// CHECK: @_ZTIPf = constant +// CHECK: @_ZTIPKf = constant // double -// CHECK: @_ZTId = unnamed_addr constant -// CHECK: @_ZTIPd = unnamed_addr constant -// CHECK: @_ZTIPKd = unnamed_addr constant +// CHECK: @_ZTId = constant +// CHECK: @_ZTIPd = constant +// CHECK: @_ZTIPKd = constant // long double -// CHECK: @_ZTIe = unnamed_addr constant -// CHECK: @_ZTIPe = unnamed_addr constant -// CHECK: @_ZTIPKe = unnamed_addr constant +// CHECK: @_ZTIe = constant +// CHECK: @_ZTIPe = constant +// CHECK: @_ZTIPKe = constant // char16_t -// CHECK: @_ZTIDs = unnamed_addr constant -// CHECK: @_ZTIPDs = unnamed_addr constant -// CHECK: @_ZTIPKDs = unnamed_addr constant +// CHECK: @_ZTIDs = constant +// CHECK: @_ZTIPDs = constant +// CHECK: @_ZTIPKDs = constant // char32_t -// CHECK: @_ZTIDi = unnamed_addr constant -// CHECK: @_ZTIPDi = unnamed_addr constant -// CHECK: @_ZTIPKDi = unnamed_addr constant +// CHECK: @_ZTIDi = constant +// CHECK: @_ZTIPDi = constant +// CHECK: @_ZTIPKDi = constant diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index 42fe435234042..3b06d426e5a99 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -1,56 +1,75 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fvisibility hidden -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-WITH-HIDDEN %s +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BOTH +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck -check-prefix=CHECK-WITH-HIDDEN -check-prefix=CHECK-BOTH %s #include <typeinfo> +// CHECK-BOTH: _ZTSP1C = internal constant +// CHECK-BOTH: _ZTS1C = internal constant +// CHECK-BOTH: _ZTI1C = internal constant +// CHECK-BOTH: _ZTIP1C = internal constant +// CHECK-BOTH: _ZTSPP1C = internal constant +// CHECK-BOTH: _ZTIPP1C = internal constant +// CHECK-BOTH: _ZTSM1Ci = internal constant +// CHECK-BOTH: _ZTIM1Ci = internal constant +// CHECK-BOTH: _ZTSPM1Ci = internal constant +// CHECK-BOTH: _ZTIPM1Ci = internal constant +// CHECK-BOTH: _ZTSM1CS_ = internal constant +// CHECK-BOTH: _ZTIM1CS_ = internal constant +// CHECK-BOTH: _ZTSM1CPS_ = internal constant +// CHECK-BOTH: _ZTIM1CPS_ = internal constant +// CHECK-BOTH: _ZTSM1A1C = internal constant +// CHECK: _ZTS1A = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTS1A = linkonce_odr hidden constant +// CHECK: _ZTI1A = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTI1A = linkonce_odr hidden constant +// CHECK-BOTH: _ZTIM1A1C = internal constant +// CHECK-BOTH: _ZTSM1AP1C = internal constant +// CHECK-BOTH: _ZTIM1AP1C = internal constant + // CHECK-WITH-HIDDEN: _ZTSFN12_GLOBAL__N_11DEvE = internal constant // CHECK-WITH-HIDDEN: @_ZTSPK2T4 = linkonce_odr hidden constant // CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden unnamed_addr constant -// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden unnamed_addr constant - -// CHECK: _ZTSP1C = internal constant -// CHECK: _ZTS1C = internal constant -// CHECK: _ZTI1C = internal unnamed_addr constant -// CHECK: _ZTIP1C = internal unnamed_addr constant -// CHECK: _ZTSPP1C = internal constant -// CHECK: _ZTIPP1C = internal unnamed_addr constant -// CHECK: _ZTSM1Ci = internal constant -// CHECK: _ZTIM1Ci = internal unnamed_addr constant -// CHECK: _ZTSPM1Ci = internal constant -// CHECK: _ZTIPM1Ci = internal unnamed_addr constant -// CHECK: _ZTSM1CS_ = internal constant -// CHECK: _ZTIM1CS_ = internal unnamed_addr constant -// CHECK: _ZTSM1CPS_ = internal constant -// CHECK: _ZTIM1CPS_ = internal unnamed_addr constant -// CHECK: _ZTSM1A1C = internal constant -// CHECK: _ZTS1A = linkonce_odr constant -// CHECK: _ZTI1A = linkonce_odr hidden unnamed_addr constant -// CHECK: _ZTIM1A1C = internal unnamed_addr constant -// CHECK: _ZTSM1AP1C = internal constant -// CHECK: _ZTIM1AP1C = internal unnamed_addr constant +// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t5vE1A = internal constant +// CHECK-WITH-HIDDEN: @_ZTIZ2t5vE1A = internal constant +// CHECK-WITH-HIDDEN: @_ZTSPZ2t7vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t7vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTIZ2t7vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTIPZ2t7vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t6vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTIZ2t6vE1A = linkonce_odr hidden constant + // CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTIN12_GLOBAL__N_11DE = internal unnamed_addr constant +// CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal unnamed_addr constant +// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant -// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal unnamed_addr constant +// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant -// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal unnamed_addr constant +// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant // CHECK: _ZTSPFvvE = linkonce_odr constant // CHECK: _ZTSFvvE = linkonce_odr constant -// CHECK: _ZTIFvvE = linkonce_odr hidden unnamed_addr constant -// CHECK: _ZTIPFvvE = linkonce_odr hidden unnamed_addr constant +// CHECK: _ZTIFvvE = linkonce_odr constant +// CHECK: _ZTIPFvvE = linkonce_odr constant // CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant -// CHECK: _ZTIN12_GLOBAL__N_11EE = internal unnamed_addr constant +// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant // CHECK: _ZTSA10_i = linkonce_odr constant -// CHECK: _ZTIA10_i = linkonce_odr hidden unnamed_addr constant -// CHECK: _ZTI1TILj0EE = linkonce_odr unnamed_addr constant -// CHECK: _ZTI1TILj1EE = weak_odr unnamed_addr constant +// CHECK: _ZTIA10_i = linkonce_odr constant +// CHECK: _ZTI1TILj0EE = linkonce_odr constant +// CHECK: _ZTI1TILj1EE = weak_odr constant // CHECK: _ZTI1TILj2EE = external constant +// CHECK: _ZTSZ2t5vE1A = internal constant +// CHECK: _ZTIZ2t5vE1A = internal constant // CHECK: _ZTS1B = constant -// CHECK: _ZTI1B = unnamed_addr constant +// CHECK: _ZTI1B = constant // CHECK: _ZTS1F = linkonce_odr constant +// CHECK: _ZTSPZ2t7vE1A = linkonce_odr constant +// CHECK: _ZTSZ2t7vE1A = linkonce_odr constant +// CHECK: _ZTIZ2t7vE1A = linkonce_odr constant +// CHECK: _ZTIPZ2t7vE1A = linkonce_odr constant +// CHECK: _ZTSZ2t6vE1A = linkonce_odr constant +// CHECK: _ZTIZ2t6vE1A = linkonce_odr constant // CHECK: _ZTIN12_GLOBAL__N_11DE to @@ -138,3 +157,25 @@ struct T4 {}; void t4(const T4 *ptr) { const void *value = &typeid(ptr); } + +// rdar://16265084 +void t5() { + struct A {}; + const void *value = &typeid(A); +} + +inline void t6() { + struct A {}; + const void *value = &typeid(A); +} +void t6_helper() { + t6(); +} + +inline void t7() { + struct A {}; + const void *value = &typeid(A*); +} +void t7_helper() { + t7(); +} diff --git a/test/CodeGenCXX/rtti-visibility.cpp b/test/CodeGenCXX/rtti-visibility.cpp index 40cee061942a3..5945be5c73a26 100644 --- a/test/CodeGenCXX/rtti-visibility.cpp +++ b/test/CodeGenCXX/rtti-visibility.cpp @@ -1,17 +1,15 @@ // 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 -fhidden-weak-vtables -emit-llvm -o %t.hidden // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t -// RUN: FileCheck --check-prefix=CHECK-TEST2-HIDDEN %s < %t.hidden #include <typeinfo> namespace Test1 { // A is explicitly marked hidden, so all RTTI data should also be marked hidden. // CHECK-TEST1: @_ZTSN5Test11AE = linkonce_odr hidden constant - // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden unnamed_addr constant + // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden constant // CHECK-TEST1: @_ZTSPN5Test11AE = linkonce_odr hidden constant - // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden unnamed_addr constant + // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden constant struct __attribute__((visibility("hidden"))) A { }; void f() { @@ -23,12 +21,8 @@ namespace Test1 { namespace Test2 { // A is weak, so its linkage should be linkoce_odr, but not marked hidden. // CHECK-TEST2: @_ZTSN5Test21AE = linkonce_odr constant - // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr unnamed_addr constant + // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr constant struct A { }; - - // With -fhidden-weak-vtables, the typeinfo for A is marked hidden, but not its name. - // CHECK-TEST2-HIDDEN: _ZTSN5Test21AE = linkonce_odr constant - // CHECK-TEST2-HIDDEN: @_ZTIN5Test21AE = linkonce_odr hidden unnamed_addr constant void f() { (void)typeid(A); } diff --git a/test/CodeGenCXX/runtimecc.cpp b/test/CodeGenCXX/runtimecc.cpp index 646c61e0fd8fb..20448838f9198 100644 --- a/test/CodeGenCXX/runtimecc.cpp +++ b/test/CodeGenCXX/runtimecc.cpp @@ -45,7 +45,7 @@ namespace test1 { // CHECK: declare arm_aapcscc void @__cxa_throw(i8*, i8*, i8*) -// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__I_a() +// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__sub_I_runtimecc.cpp() // CHECK: call arm_aapcscc void @__cxx_global_var_init() diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp index 2e0fa829ec90d..66705bfc6b3c4 100644 --- a/test/CodeGenCXX/rvalue-references.cpp +++ b/test/CodeGenCXX/rvalue-references.cpp @@ -7,8 +7,8 @@ struct B : Spacer, A { }; B &getB(); -// CHECK-LABEL: define %struct.A* @_Z4getAv() -// CHECK: call %struct.B* @_Z4getBv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.A* @_Z4getAv() +// CHECK: call dereferenceable({{[0-9]+}}) %struct.B* @_Z4getBv() // CHECK-NEXT: bitcast %struct.B* // CHECK-NEXT: getelementptr inbounds i8* // CHECK-NEXT: bitcast i8* {{.*}} to %struct.A* @@ -19,17 +19,17 @@ int &getIntLValue(); int &&getIntXValue(); int getIntPRValue(); -// CHECK-LABEL: define i32* @_Z2f0v() -// CHECK: call i32* @_Z12getIntLValuev() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f0v() +// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z12getIntLValuev() // CHECK-NEXT: ret i32* int &&f0() { return static_cast<int&&>(getIntLValue()); } -// CHECK-LABEL: define i32* @_Z2f1v() -// CHECK: call i32* @_Z12getIntXValuev() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f1v() +// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z12getIntXValuev() // CHECK-NEXT: ret i32* int &&f1() { return static_cast<int&&>(getIntXValue()); } -// CHECK-LABEL: define i32* @_Z2f2v +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f2v // CHECK: call i32 @_Z13getIntPRValuev() // CHECK-NEXT: store i32 {{.*}}, i32* // CHECK-NEXT: ret i32* @@ -95,7 +95,7 @@ namespace test1 { }; // CHECK-LABEL: define void @_ZN5test11BC2Ei( - // CHECK: [[T0:%.*]] = call i32* @_ZN5test14moveERi( + // CHECK: [[T0:%.*]] = call dereferenceable({{[0-9]+}}) i32* @_ZN5test14moveERi( // CHECK-NEXT: [[T1:%.*]] = load i32* [[T0]] // CHECK-NEXT: call void @_ZN5test11AC1Ei({{.*}}, i32 [[T1]]) // CHECK-NEXT: ret void diff --git a/test/CodeGenCXX/scoped-enums.cpp b/test/CodeGenCXX/scoped-enums.cpp index 159172d1662e7..218013a4c58b7 100644 --- a/test/CodeGenCXX/scoped-enums.cpp +++ b/test/CodeGenCXX/scoped-enums.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // PR9923 enum class Color { red, blue, green }; diff --git a/test/CodeGenCXX/sparcv9-abi.cpp b/test/CodeGenCXX/sparcv9-abi.cpp new file mode 100644 index 0000000000000..128d648cebd5e --- /dev/null +++ b/test/CodeGenCXX/sparcv9-abi.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +struct pod { + int a, b; +}; + +void f0(); +void f1(struct pod); + +struct notpod { + int a, b; + ~notpod() { f0(); } +}; + +void f2(struct notpod); + +// CHECK-LABEL: caller +// CHECK: call void @_Z2f13pod(i64 +// CHECK: call void @_Z2f26notpod(%struct.notpod* +void caller() +{ + pod p1; + notpod p2; + f1(p1); + f2(p2); +} diff --git a/test/CodeGenCXX/specialized-static-data-mem-init.cpp b/test/CodeGenCXX/specialized-static-data-mem-init.cpp index c2a2ddb11254a..68799624f26e6 100644 --- a/test/CodeGenCXX/specialized-static-data-mem-init.cpp +++ b/test/CodeGenCXX/specialized-static-data-mem-init.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // rdar: // 8562966 // pr8409 -// CHECK: @_ZN1CIiE11needs_guardE = weak_odr global -// CHECK: @_ZGVN1CIiE11needs_guardE = weak_odr global +// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr global +// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr global struct K { diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp new file mode 100644 index 0000000000000..3e120344d6b66 --- /dev/null +++ b/test/CodeGenCXX/split-stacks.cpp @@ -0,0 +1,33 @@ +// RUN: %clang -target x86_64-linux-gnu -fsplit-stack -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-SEGSTK %s +// RUN: %clang -target x86_64-linux-gnu -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-NOSEGSTK %s + +int foo() { + return 0; +} + +template <typename T> +[[gnu::no_split_stack]] +int tnosplit() { + return 0; +} + +[[gnu::no_split_stack]] +int nosplit() { + return tnosplit<int>(); +} + +// CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] { +// CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { +// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } + +// CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] { +// CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { +// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } +// CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} } diff --git a/test/CodeGenCXX/static-init-3.cpp b/test/CodeGenCXX/static-init-3.cpp index dc28d5a32a63e..083e00144c181 100644 --- a/test/CodeGenCXX/static-init-3.cpp +++ b/test/CodeGenCXX/static-init-3.cpp @@ -16,8 +16,8 @@ struct X1 } }; -// CHECK: @_ZN2X1I2X2I1BEE8instanceE = weak_odr global %struct.X2* null, align 8 -// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = weak_odr global %struct.X2* null, align 8 +// CHECK: @_ZN2X1I2X2I1BEE8instanceE = linkonce_odr global %struct.X2* null, align 8 +// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = linkonce_odr global %struct.X2* null, align 8 template<class T> T & X1<T>::instance = X1<T>::get(); class A { }; diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index f522775c109ef..d23ead47f3855 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -103,14 +103,14 @@ namespace test2 { B::B() { static int x = foo(); } - // CHECK-LABEL: define void @_ZN5test21BC1Ev + // CHECK-LABEL: define void @_ZN5test21BC2Ev // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire, // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x) // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv() // CHECK: store i32 [[T0]], i32* @_ZZN5test21BC1EvE1x, // CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BC1EvE1x) - // CHECK-LABEL: define void @_ZN5test21BC2Ev + // CHECK-LABEL: define void @_ZN5test21BC1Ev // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire, // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x) // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv() @@ -122,15 +122,15 @@ namespace test2 { B::~B() { static int y = foo(); } - // CHECK-LABEL: define void @_ZN5test21BD1Ev( - // CHECK: call void @_ZN5test21BD2Ev( - // CHECK-LABEL: define void @_ZN5test21BD2Ev( // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BD1EvE1y to i8*) acquire, // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BD1EvE1y) // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv() // CHECK: store i32 [[T0]], i32* @_ZZN5test21BD1EvE1y, // CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BD1EvE1y) + + // CHECK-LABEL: define void @_ZN5test21BD1Ev( + // CHECK: call void @_ZN5test21BD2Ev( } // This shouldn't error out. @@ -149,6 +149,6 @@ namespace test3 { union U { char x; int i; }; static U u = { 'a' }; } - // CHECK-LABEL: define void @_ZN5test31BC1Ev( // CHECK-LABEL: define void @_ZN5test31BC2Ev( + // CHECK-LABEL: define void @_ZN5test31BC1Ev( } diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp index 50772bf647d17..98c09b84797dd 100644 --- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -12,21 +12,21 @@ template<> int A<char>::a; // CHECK: @_ZN1AIbE1aE = global i32 10 template<> int A<bool>::a = 10; -// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()* }] -// CHECK: [{ i32, void ()* } { i32 65535, void ()* @[[unordered1:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered2:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered3:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered4:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered5:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered6:[^ ]*]] }, -// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] +// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()*, i8* }] +// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* bitcast (i16* @_Z1xIsE to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* bitcast (i32* @_ZN1AIvE1aE to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }] template int A<short>::a; // Unordered int b = foo(); int c = foo(); int d = A<void>::a; // Unordered -// An explicit specialization is ordered, and goes in __GLOBAL_I_a. +// An explicit specialization is ordered, and goes in __GLOBAL_sub_I_static_member_variable_explicit_specialization.cpp. template<> struct A<int> { static int a; }; int A<int>::a = foo(); @@ -82,7 +82,7 @@ template int b::i<int>; // CHECK: store {{.*}} @_Z1xIcE // CHECK: ret -// CHECK: define internal void @_GLOBAL__I_a() +// CHECK: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp() // We call unique stubs for every ordered dynamic initializer in the TU. // CHECK: call // CHECK: call diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp index 5d4d6bcce4583..7bf19bbfb46df 100644 --- a/test/CodeGenCXX/stmtexpr.cpp +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-unused-value -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // rdar: //8540501 extern "C" int printf(...); extern "C" void abort(); diff --git a/test/CodeGenCXX/template-dependent-bind-temporary.cpp b/test/CodeGenCXX/template-dependent-bind-temporary.cpp index ca980c3ff6854..47d8279a47749 100644 --- a/test/CodeGenCXX/template-dependent-bind-temporary.cpp +++ b/test/CodeGenCXX/template-dependent-bind-temporary.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // rdar: //8620524 // PR7851 struct string { diff --git a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp index de86f10f6c30d..137792b26a43a 100644 --- a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp +++ b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -fvisibility hidden -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fvisibility hidden -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // Verify that symbols are hidden. // CHECK: @_ZN1CIiE5Inner6Inner26StaticE = weak_odr hidden global -// CHECK-LABEL: define weak_odr hidden void @_ZN1CIiE5Inner1fEv -// CHECK-LABEL: define weak_odr hidden void @_ZN1CIiE5Inner6Inner21gEv +// CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1CIiE5Inner1fEv +// CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1CIiE5Inner6Inner21gEv template<typename T> struct C { diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp index 80283a1edd047..90b8099f0a26c 100644 --- a/test/CodeGenCXX/template-instantiation.cpp +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -5,10 +5,14 @@ // // CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant // CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE -// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant +// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA1_iEE +// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE +// CHECK: @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant -// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32] -// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A +// CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32] +// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A + +// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant // CHECK-NOT: _ZTVN5test31SIiEE // CHECK-NOT: _ZTSN5test31SIiEE @@ -39,11 +43,21 @@ namespace test0 { virtual void xsgetn(); }; - // This specialization should cause the vtable to be emitted, even with - // the following extern template declaration. - template<> void stdio_sync_filebuf<wchar_t>::xsgetn() { + // This specialization is not a key function, so doesn't cause the vtable to + // be instantiated unless we're instantiating a class definition anyway. + template<> void stdio_sync_filebuf<int[1]>::xsgetn() { + } + template<> void stdio_sync_filebuf<int[2]>::xsgetn() { + } + template<> void stdio_sync_filebuf<int[3]>::xsgetn() { } - extern template class stdio_sync_filebuf<wchar_t>; + template<> void stdio_sync_filebuf<int[4]>::xsgetn() { + } + extern template class stdio_sync_filebuf<int[2]>; + + // These two both cause vtables to be emitted. + template class stdio_sync_filebuf<int[3]>; + stdio_sync_filebuf<int[4]> implicit_instantiation; } namespace test1 { diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index e8a7a1f255961..7f5c7af038654 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -3,8 +3,8 @@ namespace PR16263 { const unsigned int n = 1234; extern const int &r = (const int&)n; - // CHECK: @_ZGRN7PR162631rE = private constant i32 1234, - // CHECK: @_ZN7PR162631rE = constant i32* @_ZGRN7PR162631rE, + // CHECK: @_ZGRN7PR162631rE_ = private constant i32 1234, + // CHECK: @_ZN7PR162631rE = constant i32* @_ZGRN7PR162631rE_, extern const int &s = reinterpret_cast<const int&>(n); // CHECK: @_ZN7PR16263L1nE = internal constant i32 1234, align 4 @@ -14,17 +14,32 @@ namespace PR16263 { struct B { int n; }; struct C : A, B {}; extern const A &&a = (A&&)(A&&)(C&&)(C{}); - // CHECK: @_ZGRN7PR162631aE = private global {{.*}} zeroinitializer, - // CHECK: @_ZN7PR162631aE = constant {{.*}} bitcast ({{.*}}* @_ZGRN7PR162631aE to + // CHECK: @_ZGRN7PR162631aE_ = private global {{.*}} zeroinitializer, + // CHECK: @_ZN7PR162631aE = constant {{.*}} bitcast ({{.*}}* @_ZGRN7PR162631aE_ to extern const int &&t = ((B&&)C{}).n; - // CHECK: @_ZGRN7PR162631tE = private global {{.*}} zeroinitializer, - // CHECK: @_ZN7PR162631tE = constant i32* {{.*}}* @_ZGRN7PR162631tE {{.*}} 4 + // CHECK: @_ZGRN7PR162631tE_ = private global {{.*}} zeroinitializer, + // CHECK: @_ZN7PR162631tE = constant i32* {{.*}}* @_ZGRN7PR162631tE_ {{.*}} 4 struct D { double d; C c; }; extern const int &&u = (123, static_cast<B&&>(0, ((D&&)D{}).*&D::c).n); - // CHECK: @_ZGRN7PR162631uE = private global {{.*}} zeroinitializer - // CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE {{.*}} 12 + // CHECK: @_ZGRN7PR162631uE_ = private global {{.*}} zeroinitializer + // CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE_ {{.*}} 12 +} + +namespace PR20227 { + struct A { ~A(); }; + struct B { virtual ~B(); }; + struct C : B {}; + + A &&a = dynamic_cast<A&&>(A{}); + // CHECK: @_ZGRN7PR202271aE_ = private global + + B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{})); + // CHECK: @_ZGRN7PR202271bE_ = private global + + B &&c = static_cast<C&&>(static_cast<B&&>(C{})); + // CHECK: @_ZGRN7PR202271cE_ = private global } struct A { @@ -310,7 +325,7 @@ int& f(int); void g() { // CHECK: call void @_ZN3T121AC1Ev // CHECK-NEXT: call i32 @_ZN3T121A1fEv( - // CHECK-NEXT: call i32* @_ZN3T121fEi( + // CHECK-NEXT: call dereferenceable({{[0-9]+}}) i32* @_ZN3T121fEi( // CHECK-NEXT: call void @_ZN3T121AD1Ev( int& i = f(A().f()); } @@ -325,7 +340,7 @@ namespace PR6648 { struct D; D& zed(B); void foobar() { - // CHECK: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE + // CHECK: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE zed(foo); } } @@ -412,10 +427,10 @@ namespace Elision { // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8 // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[I]]) - // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* [[X:%.*]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]]) A i = (c ? A() : x); - // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* [[X]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* dereferenceable({{[0-9]+}}) [[X]]) // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[J]]) A j = (c ? x : A()); @@ -435,10 +450,10 @@ namespace Elision { A test3(int v, A x) { if (v < 5) // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]]) - // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X:%.*]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]]) return (v < 0 ? A() : x); else - // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X]]) // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET]]) return (v > 10 ? x : A()); @@ -456,7 +471,7 @@ namespace Elision { // CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i64 0, i64 0 // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]]) // CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]]* [[XS0]], i64 1 - // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* [[X]]) + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* dereferenceable({{[0-9]+}}) [[X]]) A xs[] = { A(), x }; // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 0 @@ -483,7 +498,7 @@ namespace Elision { // CHECK: call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]]) // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0 - // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]]) // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]]) // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]]) // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]]) @@ -491,13 +506,13 @@ namespace Elision { // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]]) // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0 - // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]]) // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]]) A x = B().a; // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]]) // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0 - // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]]) // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]]) return B().a; @@ -596,23 +611,23 @@ namespace BindToSubobject { void f(), g(); - // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE) - // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1aE to i8*), i8* @__dso_handle) - // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1aE, i32 0, i32 0), i32** @_ZN15BindToSubobject1aE, align 8 + // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE_) + // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1aE_ to i8*), i8* @__dso_handle) + // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1aE_, i32 0, i32 0), i32** @_ZN15BindToSubobject1aE, align 8 int &&a = A().a; // CHECK: call void @_ZN15BindToSubobject1fEv() - // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE) - // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1bE to i8*), i8* @__dso_handle) - // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1bE, i32 0, i32 0), i32** @_ZN15BindToSubobject1bE, align 8 + // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE_) + // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1bE_ to i8*), i8* @__dso_handle) + // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1bE_, i32 0, i32 0), i32** @_ZN15BindToSubobject1bE, align 8 int &&b = (f(), A().a); int A::*h(); // CHECK: call void @_ZN15BindToSubobject1fEv() // CHECK: call void @_ZN15BindToSubobject1gEv() - // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE) - // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1cE to i8*), i8* @__dso_handle) + // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE_) + // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1cE_ to i8*), i8* @__dso_handle) // CHECK: call {{.*}} @_ZN15BindToSubobject1hE // CHECK: getelementptr // CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1cE, align 8 @@ -623,8 +638,8 @@ namespace BindToSubobject { A a; }; - // CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE) - // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1BD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1dE to i8*), i8* @__dso_handle) + // CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE_) + // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1BD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1dE_ to i8*), i8* @__dso_handle) // CHECK: call {{.*}} @_ZN15BindToSubobject1hE // CHECK: getelementptr {{.*}} getelementptr // CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1dE, align 8 @@ -637,9 +652,9 @@ namespace Bitfield { // Do not lifetime extend the S() temporary here. // CHECK: alloca // CHECK: call {{.*}}memset - // CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE + // CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE_ // CHECK: call void @_ZN8Bitfield1SD1 - // CHECK: store i32* @_ZGRN8Bitfield1rE, i32** @_ZN8Bitfield1rE, align 8 + // CHECK: store i32* @_ZGRN8Bitfield1rE_, i32** @_ZN8Bitfield1rE, align 8 int &&r = S().a; } @@ -652,14 +667,14 @@ namespace Vector { }; // CHECK: alloca // CHECK: extractelement - // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE - // CHECK: store i32* @_ZGRN6Vector1rE, i32** @_ZN6Vector1rE, + // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE_ + // CHECK: store i32* @_ZGRN6Vector1rE_, i32** @_ZN6Vector1rE, int &&r = S().v[1]; // CHECK: alloca // CHECK: extractelement - // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE - // CHECK: store i32* @_ZGRN6Vector1sE, i32** @_ZN6Vector1sE, + // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE_ + // CHECK: store i32* @_ZGRN6Vector1sE_, i32** @_ZN6Vector1sE, int &&s = S().w[1]; // FIXME PR16204: The following code leads to an assertion in Sema. //int &&s = S().w.y; @@ -761,8 +776,8 @@ namespace PR14130 { struct S { S(int); }; struct U { S &&s; }; U v { { 0 } }; - // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE, i32 0) - // CHECK: store {{.*}} @_ZGRN7PR141301vE, {{.*}} @_ZN7PR141301vE + // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0) + // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE } namespace Ctor { diff --git a/test/CodeGenCXX/throw-expression-dtor.cpp b/test/CodeGenCXX/throw-expression-dtor.cpp index cb4a6c69bdddf..b883b856be3cd 100644 --- a/test/CodeGenCXX/throw-expression-dtor.cpp +++ b/test/CodeGenCXX/throw-expression-dtor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm-only -verify -fcxx-exceptions -fexceptions +// RUN: %clang_cc1 %s -emit-llvm-only -verify -triple %itanium_abi_triple -fcxx-exceptions -fexceptions // expected-no-diagnostics // PR7281 diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp index d9bf8fdd59ea7..4dd5322fba515 100644 --- a/test/CodeGenCXX/throw-expressions.cpp +++ b/test/CodeGenCXX/throw-expressions.cpp @@ -67,3 +67,48 @@ int test6(bool x, bool y, int z) { // // end: // CHECK: ret i32 + +namespace DR1560 { + struct A { + ~A(); + }; + extern bool b; + A get(); + // CHECK-LABEL: @_ZN6DR15601bE + const A &r = b ? get() : throw 0; + // CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN6DR15601AD1Ev {{.*}} @_ZGRN6DR15601rE + // CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev +} + +// CHECK-LABEL: define void @_Z5test7b( +void test7(bool cond) { + // CHECK: br i1 + // + // x.true: + // CHECK: call void @__cxa_throw( + // CHECK-NEXT: unreachable + // + // x.false: + // CHECK: br label + // + // end: + // CHECK: ret void + cond ? throw test7 : val; +} + +// CHECK-LABEL: define dereferenceable(4) i32* @_Z5test8b( +int &test8(bool cond) { + // CHECK: br i1 + // + // x.true: + // CHECK: br label + // + // x.false: + // CHECK: call void @__cxa_throw( + // CHECK-NEXT: unreachable + // + // end: + // CHECK: ret i32* @val + return cond ? val : ((throw "foo")); +} diff --git a/test/CodeGenCXX/thunk-use-after-free.cpp b/test/CodeGenCXX/thunk-use-after-free.cpp index d70e9025683d7..14f2356ea456b 100644 --- a/test/CodeGenCXX/thunk-use-after-free.cpp +++ b/test/CodeGenCXX/thunk-use-after-free.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -O1 %s +// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -O1 %s // This used to crash under asan and valgrind. // PR12284 diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index defb70681d93d..89e4db394821e 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-HIDDEN %s namespace Test1 { @@ -251,9 +250,7 @@ namespace Test10 { struct B { virtual void foo(); }; struct C : A, B { void foo() {} }; - // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv - // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv - + // Test later. void test() { C c; } @@ -366,6 +363,10 @@ namespace Test15 { /**** The following has to go at the end of the file ****/ +// This is from Test10: +// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv +// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv + // This is from Test5: // CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv // CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( diff --git a/test/CodeGenCXX/tls-init-funcs.cpp b/test/CodeGenCXX/tls-init-funcs.cpp index 17299dcb7b6ce..d47329cdc29fa 100644 --- a/test/CodeGenCXX/tls-init-funcs.cpp +++ b/test/CodeGenCXX/tls-init-funcs.cpp @@ -1,10 +1,34 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++1y -S -emit-llvm %s -o - | FileCheck %s // CHECK: @a = internal thread_local global +// CHECK: @_Z2vtIiE = internal thread_local global i32 5 +// CHECK: @_ZZ3inlvE3loc = linkonce_odr thread_local global i32 0 // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev +// CHECK: call i32* @_ZTW3ext() +// CHECK: declare i32* @_ZTW3ext() +// CHECK: define weak i32* @_ZTW2vtIiE() +// CHECK: define weak i32* @_ZTW2vtIvE() +// CHECK: define {{.*}} @_ZTW1a struct A { ~A(); }; thread_local A a; + +extern thread_local int ext; +int &get_ext() { return ext; } + +template <typename T> +thread_local int vt = 5; + +int get_vt() { return vt<int>; } + +inline int &inl() { + thread_local int loc; + return loc; +} +int &use_inl() { return inl(); } + +template int vt<void>; +int &get_vt_void() { return vt<void>; } diff --git a/test/CodeGenCXX/trivial-constructor-init.cpp b/test/CodeGenCXX/trivial-constructor-init.cpp index 65ed45e259c54..9130e4e5d959e 100644 --- a/test/CodeGenCXX/trivial-constructor-init.cpp +++ b/test/CodeGenCXX/trivial-constructor-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 -triple %itanium_abi_triple | FileCheck %s extern "C" int printf(...); diff --git a/test/CodeGenCXX/unary-type-trait.cpp b/test/CodeGenCXX/type-traits.cpp index 3c6f9c03aa413..93cc6b56f1d26 100644 --- a/test/CodeGenCXX/unary-type-trait.cpp +++ b/test/CodeGenCXX/type-traits.cpp @@ -2,3 +2,5 @@ // expected-no-diagnostics bool a() { return __is_pod(int); } + +bool b() { return __is_trivially_constructible(int, int, int); } diff --git a/test/CodeGenCXX/type_visibility.cpp b/test/CodeGenCXX/type_visibility.cpp index 11e5091fd279d..a7b7198a23fab 100644 --- a/test/CodeGenCXX/type_visibility.cpp +++ b/test/CodeGenCXX/type_visibility.cpp @@ -29,11 +29,11 @@ namespace temp0 { // FUNS-LABEL: define weak_odr void @_ZN5temp01BINS_1AEE3fooEv( // VARS: @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant // VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant - // VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr unnamed_addr constant + // VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp01BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant - // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant } namespace temp1 { @@ -46,11 +46,11 @@ namespace temp1 { // FUNS-LABEL: define weak_odr void @_ZN5temp11BINS_1AEE3fooEv( // VARS: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant // VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant - // VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr unnamed_addr constant + // VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp11BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant // VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant - // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr constant } namespace temp2 { @@ -63,11 +63,11 @@ namespace temp2 { // FUNS-LABEL: define weak_odr void @_ZN5temp21BINS_1AEE3fooEv( // VARS: @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant // VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant - // VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr unnamed_addr constant + // VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp21BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant - // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant } namespace temp3 { @@ -80,11 +80,11 @@ namespace temp3 { // FUNS-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv( // VARS: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant - // VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant - // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant } namespace temp4 { @@ -97,11 +97,11 @@ namespace temp4 { // FUNS-LABEL: define weak_odr void @_ZN5temp41BINS_1AEE3fooEv( // VARS: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant - // VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp41BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant - // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant } namespace type0 { @@ -113,11 +113,11 @@ namespace type0 { // FUNS-LABEL: define void @_ZN5type01A3fooEv( // VARS: @_ZTVN5type01AE = unnamed_addr constant // VARS: @_ZTSN5type01AE = constant - // VARS: @_ZTIN5type01AE = unnamed_addr constant + // VARS: @_ZTIN5type01AE = constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv( // VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant // VARS-HIDDEN: @_ZTSN5type01AE = constant - // VARS-HIDDEN: @_ZTIN5type01AE = unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5type01AE = constant } namespace type1 { @@ -129,11 +129,11 @@ namespace type1 { // FUNS-LABEL: define hidden void @_ZN5type11A3fooEv( // VARS: @_ZTVN5type11AE = unnamed_addr constant // VARS: @_ZTSN5type11AE = constant - // VARS: @_ZTIN5type11AE = unnamed_addr constant + // VARS: @_ZTIN5type11AE = constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv( // VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant // VARS-HIDDEN: @_ZTSN5type11AE = constant - // VARS-HIDDEN: @_ZTIN5type11AE = unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5type11AE = constant } namespace type2 { @@ -145,11 +145,11 @@ namespace type2 { // FUNS-LABEL: define void @_ZN5type21A3fooEv( // VARS: @_ZTVN5type21AE = hidden unnamed_addr constant // VARS: @_ZTSN5type21AE = hidden constant - // VARS: @_ZTIN5type21AE = hidden unnamed_addr constant + // VARS: @_ZTIN5type21AE = hidden constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type21A3fooEv( // VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5type21AE = hidden constant - // VARS-HIDDEN: @_ZTIN5type21AE = hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5type21AE = hidden constant } namespace type3 { @@ -161,10 +161,10 @@ namespace type3 { // FUNS-LABEL: define void @_ZN5type31A3fooEv( // VARS: @_ZTVN5type31AE = hidden unnamed_addr constant // VARS: @_ZTSN5type31AE = hidden constant - // VARS: @_ZTIN5type31AE = hidden unnamed_addr constant + // VARS: @_ZTIN5type31AE = hidden constant // FUNS-HIDDEN-LABEL: define void @_ZN5type31A3fooEv( // VARS-HIDDEN: @_ZTVN5type31AE = hidden unnamed_addr constant // VARS-HIDDEN: @_ZTSN5type31AE = hidden constant - // VARS-HIDDEN: @_ZTIN5type31AE = hidden unnamed_addr constant + // VARS-HIDDEN: @_ZTIN5type31AE = hidden constant } diff --git a/test/CodeGenCXX/typeid-should-throw.cpp b/test/CodeGenCXX/typeid-should-throw.cpp new file mode 100644 index 0000000000000..1d8fc85896af4 --- /dev/null +++ b/test/CodeGenCXX/typeid-should-throw.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -Wno-unused-value -emit-llvm -o - -std=c++11 | FileCheck %s +namespace std { +struct type_info; +} + +struct A { + virtual ~A(); + operator bool(); +}; +struct B : A {}; + +void f1(A *x) { typeid(false, *x); } +// CHECK-LABEL: define void @_Z2f1P1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f2(bool b, A *x, A *y) { typeid(b ? *x : *y); } +// CHECK-LABEL: define void @_Z2f2bP1AS0_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f3(bool b, A *x, A &y) { typeid(b ? *x : y); } +// CHECK-LABEL: define void @_Z2f3bP1ARS_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f4(bool b, A &x, A *y) { typeid(b ? x : *y); } +// CHECK-LABEL: define void @_Z2f4bR1APS_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f5(volatile A *x) { typeid(*x); } +// CHECK-LABEL: define void @_Z2f5PV1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f6(A *x) { typeid((B &)*(B *)x); } +// CHECK-LABEL: define void @_Z2f6P1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f7(A *x) { typeid((*x)); } +// CHECK-LABEL: define void @_Z2f7P1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f8(A *x) { typeid(x[0]); } +// CHECK-LABEL: define void @_Z2f8P1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f9(A *x) { typeid(0[x]); } +// CHECK-LABEL: define void @_Z2f9P1A +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f10(A *x, A *y) { typeid(*y ?: *x); } +// CHECK-LABEL: define void @_Z3f10P1AS0_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f11(A *x, A &y) { typeid(*x ?: y); } +// CHECK-LABEL: define void @_Z3f11P1ARS_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f12(A &x, A *y) { typeid(x ?: *y); } +// CHECK-LABEL: define void @_Z3f12R1APS_ +// CHECK: icmp eq {{.*}}, null +// CHECK-NEXT: br i1 + +void f13(A &x, A &y) { typeid(x ?: y); } +// CHECK-LABEL: define void @_Z3f13R1AS0_ +// CHECK-NOT: icmp eq {{.*}}, null + +void f14(A *x) { typeid((const A &)(A)*x); } +// CHECK-LABEL: define void @_Z3f14P1A +// CHECK-NOT: icmp eq {{.*}}, null + +void f15(A *x) { typeid((A &&)*(A *)nullptr); } +// CHECK-LABEL: define void @_Z3f15P1A +// CHECK-NOT: icmp eq {{.*}}, null diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp new file mode 100644 index 0000000000000..77996f656e010 --- /dev/null +++ b/test/CodeGenCXX/uncopyable-args.cpp @@ -0,0 +1,206 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=WIN64 + +namespace trivial { +// Trivial structs should be passed directly. +struct A { + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// CHECK-LABEL: define void @_ZN7trivial3barEv() +// CHECK: alloca %"struct.trivial::A" +// CHECK: load i8** +// CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}}) +// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*) + +// WIN64-LABEL: declare void @"\01?foo@trivial@@YAXUA@1@@Z"(i64) +} + +namespace default_ctor { +struct A { + A(); + void *p; +}; +void foo(A); +void bar() { + // Core issue 1590. We can pass this type in registers, even though C++ + // normally doesn't permit copies when using braced initialization. + foo({}); +} +// CHECK-LABEL: define void @_ZN12default_ctor3barEv() +// CHECK: alloca %"struct.default_ctor::A" +// CHECK: call void @_Z{{.*}}C1Ev( +// CHECK: load i8** +// CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}}) +// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*) + +// WIN64-LABEL: declare void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64) +} + +namespace move_ctor { +// The presence of a move constructor implicitly deletes the trivial copy ctor +// and means that we have to pass this struct by address. +struct A { + A(); + A(A &&o); + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// FIXME: The copy ctor is implicitly deleted. +// CHECK-DISABLED-LABEL: define void @_ZN9move_ctor3barEv() +// CHECK-DISABLED: call void @_Z{{.*}}C1Ev( +// CHECK-DISABLED-NOT: call +// CHECK-DISABLED: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}}) +// CHECK-DISABLED-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*) + +// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*) +} + +namespace all_deleted { +struct A { + A(); + A(const A &o) = delete; + A(A &&o) = delete; + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// FIXME: The copy ctor is deleted. +// CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv() +// CHECK-DISABLED: call void @_Z{{.*}}C1Ev( +// CHECK-DISABLED-NOT call +// CHECK-DISABLED: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}}) +// CHECK-DISABLED-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*) + +// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*) +} + +namespace implicitly_deleted { +struct A { + A(); + A &operator=(A &&o); + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// FIXME: The copy and move ctors are implicitly deleted. +// CHECK-DISABLED-LABEL: define void @_ZN18implicitly_deleted3barEv() +// CHECK-DISABLED: call void @_Z{{.*}}C1Ev( +// CHECK-DISABLED-NOT call +// CHECK-DISABLED: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}}) +// CHECK-DISABLED-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*) + +// WIN64-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*) +} + +namespace one_deleted { +struct A { + A(); + A(A &&o) = delete; + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// FIXME: The copy constructor is implicitly deleted. +// CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv() +// CHECK-DISABLED: call void @_Z{{.*}}C1Ev( +// CHECK-DISABLED-NOT call +// CHECK-DISABLED: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}}) +// CHECK-DISABLED-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*) + +// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*) +} + +namespace copy_defaulted { +struct A { + A(); + A(const A &o) = default; + A(A &&o) = delete; + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// CHECK-LABEL: define void @_ZN14copy_defaulted3barEv() +// CHECK: call void @_Z{{.*}}C1Ev( +// CHECK: load i8** +// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}}) +// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*) + +// WIN64-LABEL: declare void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64) +} + +namespace move_defaulted { +struct A { + A(); + A(const A &o) = delete; + A(A &&o) = default; + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// CHECK-LABEL: define void @_ZN14move_defaulted3barEv() +// CHECK: call void @_Z{{.*}}C1Ev( +// CHECK: load i8** +// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}}) +// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*) + +// WIN64-LABEL: declare void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*) +} + +namespace trivial_defaulted { +struct A { + A(); + A(const A &o) = default; + void *p; +}; +void foo(A); +void bar() { + foo({}); +} +// CHECK-LABEL: define void @_ZN17trivial_defaulted3barEv() +// CHECK: call void @_Z{{.*}}C1Ev( +// CHECK: load i8** +// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}}) +// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*) + +// WIN64-LABEL: declare void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64) +} + +namespace two_copy_ctors { +struct A { + A(); + A(const A &) = default; + A(const A &, int = 0); + void *p; +}; +struct B : A {}; + +void foo(B); +void bar() { + foo({}); +} +// FIXME: This class has a non-trivial copy ctor and a trivial copy ctor. It's +// not clear whether we should pass by address or in registers. +// CHECK-DISABLED-LABEL: define void @_ZN14two_copy_ctors3barEv() +// CHECK-DISABLED: call void @_Z{{.*}}C1Ev( +// CHECK-DISABLED: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}}) +// CHECK-DISABLED-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*) + +// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*) +} diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index fad459b481bfc..423d9736b4a84 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -262,6 +262,59 @@ namespace PR11124 { void r170806_a(bool b = bool()); void r170806_b() { r170806_a(); } +namespace PR20256 { + struct data { int i; }; + + template<typename T = int> + data g() { + data d; // not value-init + return d; + } + template data g(); + // CHECK-LABEL: define {{.*}} @_ZN7PR202561gIiEENS_4dataEv( + // CHECK-NOT: store + // CHECK-NOT: memset + // CHECK: } + + template<typename ...T> + data h(T ...t) { + data d(t...); // value-init + return d; + } + template data h(); + // CHECK-LABEL: define {{.*}} @_ZN7PR202561hIJEEENS_4dataEDpT_( + // CHECK: call void @llvm.memset + // CHECK: } + + + template<typename T = int> + data j() { + data d = {}; // value-init + return d; + } + template data j(); + // CHECK-LABEL: define {{.*}} @_ZN7PR202561jIiEENS_4dataEv( + // CHECK: call void @llvm.memset + // CHECK: } + + data f() { + data d; // not value-init + return d; + } + // CHECK-LABEL: define {{.*}} @_ZN7PR202561fEv( + // CHECK-NOT: store + // CHECK-NOT: memset + // CHECK: } + + data i() { + data d = {}; // value-init + return d; + } + // CHECK-LABEL: define {{.*}} @_ZN7PR202561iEv( + // CHECK: call void @llvm.memset + // CHECK: } +} + // CHECK-LABEL: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev diff --git a/test/CodeGenCXX/vararg-non-pod.cpp b/test/CodeGenCXX/vararg-non-pod.cpp index 9497179ddf050..613b28c736f08 100644 --- a/test/CodeGenCXX/vararg-non-pod.cpp +++ b/test/CodeGenCXX/vararg-non-pod.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-error=non-pod-varargs -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s struct X { X(); diff --git a/test/CodeGenCXX/virt-dtor-gen.cpp b/test/CodeGenCXX/virt-dtor-gen.cpp index 78a0b8193d74a..ba836896c2cd8 100644 --- a/test/CodeGenCXX/virt-dtor-gen.cpp +++ b/test/CodeGenCXX/virt-dtor-gen.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -o - -emit-llvm %s | FileCheck %s +// RUN: %clang_cc1 -o - -triple %itanium_abi_triple -emit-llvm %s | FileCheck %s // PR5483 // Make sure we generate all three forms of the destructor when it is virtual. @@ -7,4 +7,4 @@ class Foo { }; Foo::~Foo() {} -// CHECK-LABEL: define void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr +// CHECK-LABEL: define {{.*}}void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr diff --git a/test/CodeGenCXX/virt-dtor-key.cpp b/test/CodeGenCXX/virt-dtor-key.cpp index a8fa371d3fa83..40c5a537cc539 100644 --- a/test/CodeGenCXX/virt-dtor-key.cpp +++ b/test/CodeGenCXX/virt-dtor-key.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -// CHECK: @_ZTI3foo = unnamed_addr constant +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// CHECK: @_ZTI3foo = constant class foo { foo(); virtual ~foo(); diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp index a6067d62c61d2..a71db48a79a04 100644 --- a/test/CodeGenCXX/virt-template-vtable.cpp +++ b/test/CodeGenCXX/virt-template-vtable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s template<class T> class A { public: diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp index 40e68f672232d..6a4894b63b709 100644 --- a/test/CodeGenCXX/virtual-base-cast.cpp +++ b/test/CodeGenCXX/virtual-base-cast.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple i686-pc-linux-gnu | FileCheck %s -// RUN: %clang_cc1 -cxx-abi microsoft -emit-llvm %s -o - -triple i686-pc-win32 | FileCheck -check-prefix MSVC %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple i686-pc-win32 | FileCheck -check-prefix MSVC %s struct A { int a; virtual int aa(); }; struct B { int b; virtual int bb(); }; diff --git a/test/CodeGenCXX/virtual-base-ctor.cpp b/test/CodeGenCXX/virtual-base-ctor.cpp index 2d81ebd3a407d..8c28965c5c2f8 100644 --- a/test/CodeGenCXX/virtual-base-ctor.cpp +++ b/test/CodeGenCXX/virtual-base-ctor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -O2 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s struct B; extern B x; diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp index 5014eaf2643b1..3d790715822e3 100644 --- a/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s struct basic_ios{~basic_ios(); }; diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 2878e95b52cdb..e9c568c31b488 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -12,16 +12,16 @@ struct B : virtual A { B(); }; -// CHECK-LABEL: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr // CHECK-LABEL: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) unnamed_addr +// CHECK-LABEL: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr B::B() { } struct C : virtual A { C(bool); }; -// CHECK-LABEL: define void @_ZN1CC1Eb(%struct.C* %this, i1 zeroext) unnamed_addr // CHECK-LABEL: define void @_ZN1CC2Eb(%struct.C* %this, i8** %vtt, i1 zeroext) unnamed_addr +// CHECK-LABEL: define void @_ZN1CC1Eb(%struct.C* %this, i1 zeroext) unnamed_addr C::C(bool) { } // PR6251 diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index ae3704f369286..3e7fa8293af81 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -20,16 +20,16 @@ struct B : A { // CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev // CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev -// Deleting dtor: defers to the complete dtor. -// CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr -// CHECK: call void @_ZN1BD1Ev -// CHECK: call void @_ZdlPv - // Base dtor: actually calls A's base dtor. // CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN6MemberD1Ev // CHECK: call void @_ZN1AD2Ev +// Deleting dtor: defers to the complete dtor. +// CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr +// CHECK: call void @_ZN1BD1Ev +// CHECK: call void @_ZdlPv + B::~B() { } struct C : B { diff --git a/test/CodeGenCXX/virtual-destructor-synthesis.cpp b/test/CodeGenCXX/virtual-destructor-synthesis.cpp index 90f66a817db11..80d1b1e4ec75a 100644 --- a/test/CodeGenCXX/virtual-destructor-synthesis.cpp +++ b/test/CodeGenCXX/virtual-destructor-synthesis.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s struct box { virtual ~box(); diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp index e1b380fe7369a..0a6fc6b3f284f 100644 --- a/test/CodeGenCXX/virtual-function-calls.cpp +++ b/test/CodeGenCXX/virtual-function-calls.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s // PR5021 namespace PR5021 { @@ -8,7 +8,7 @@ struct A { }; void f(A *a) { - // CHECK: call void % + // CHECK: call {{.*}}void % a->f('c'); } @@ -45,7 +45,7 @@ namespace VirtualNoreturn { // CHECK: @_ZN15VirtualNoreturn1f void f(A *p) { p->f(); - // CHECK: call void %{{[^#]*$}} + // CHECK: call {{.*}}void %{{[^#]*$}} // CHECK-NOT: unreachable } } diff --git a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp index 70bc6fceb3612..031046597e8b3 100644 --- a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp +++ b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s struct D; struct B { diff --git a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp index d8ac1ed4c4890..7c28fb11215c2 100644 --- a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp +++ b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -std=c++11 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++11 -o - %s | FileCheck %s struct D; struct B { diff --git a/test/CodeGenCXX/virtual-inherited-destructor.cpp b/test/CodeGenCXX/virtual-inherited-destructor.cpp index 509d40ae2fef3..3ca7b6df8c3d4 100644 --- a/test/CodeGenCXX/virtual-inherited-destructor.cpp +++ b/test/CodeGenCXX/virtual-inherited-destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm-only +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm-only struct A { virtual ~A(); }; struct B : A { diff --git a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp index 0d3574e46d336..b14a34d8b5878 100644 --- a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s struct A { virtual ~A(); diff --git a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp index 549e674740ffa..95e8e089cc12b 100644 --- a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp +++ b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -O1 -emit-llvm -o - -fvisibility hidden %s | FileCheck %s +// RUN: %clang_cc1 -O1 -triple %itanium_abi_triple -emit-llvm -o - -fvisibility hidden %s | FileCheck %s template<typename T> struct X { @@ -14,13 +14,13 @@ extern template struct X<char>; // <rdar://problem/8109763> void test_X(X<int> xi, X<char> xc) { - // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1fEv + // CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1XIiE1fEv xi.f(); - // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1gEv + // CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1XIiE1gEv xi.g(); - // CHECK: declare void @_ZN1XIcE1fEv + // CHECK: declare {{.*}}void @_ZN1XIcE1fEv xc.f(); - // CHECK-LABEL: define available_externally void @_ZN1XIcE1gEv + // CHECK-LABEL: define available_externally {{.*}}void @_ZN1XIcE1gEv xc.g(); } diff --git a/test/CodeGenCXX/visibility-ms-compat.cpp b/test/CodeGenCXX/visibility-ms-compat.cpp index 25446cdf06f9a..963b2a4e6d698 100644 --- a/test/CodeGenCXX/visibility-ms-compat.cpp +++ b/test/CodeGenCXX/visibility-ms-compat.cpp @@ -27,7 +27,7 @@ namespace test0 { const std::type_info &ti = typeid(A); // CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant - // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr constant // CHECK-GLOBAL: @_ZN5test02tiE = hidden constant } @@ -43,7 +43,7 @@ namespace test1 { const std::type_info &ti = typeid(A); // CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant - // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden constant // CHECK-GLOBAL: @_ZN5test12tiE = hidden constant } @@ -59,7 +59,7 @@ namespace test2 { const std::type_info &ti = typeid(A); // CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant - // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr constant // CHECK-GLOBAL: @_ZN5test22tiE = hidden constant } @@ -76,7 +76,7 @@ namespace test3 { const std::type_info &ti = typeid(B<A>); // CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant - // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr constant } namespace test4 { @@ -92,7 +92,7 @@ namespace test4 { const std::type_info &ti = typeid(B<A>); // CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant - // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr constant } namespace test5 { @@ -108,5 +108,5 @@ namespace test5 { const std::type_info &ti = typeid(B<A>); // CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant - // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden unnamed_addr constant + // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden constant } diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp index b22f21c3faf3e..a6616d374fedf 100644 --- a/test/CodeGenCXX/vla.cpp +++ b/test/CodeGenCXX/vla.cpp @@ -9,7 +9,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 = weak_odr global i32 5 + // CHECK: @_ZN1SIiE1nE = linkonce_odr global i32 5 int a[S<int>::n]; return sizeof a; } diff --git a/test/CodeGenCXX/volatile-1.cpp b/test/CodeGenCXX/volatile-1.cpp index 71ff1ed7d6894..20389364b5248 100644 --- a/test/CodeGenCXX/volatile-1.cpp +++ b/test/CodeGenCXX/volatile-1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-unused-value -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s // CHECK: @i = global [[INT:i[0-9]+]] 0 volatile int i, j, k; @@ -248,11 +248,11 @@ void test() { // gcc. // Not a use. gcc forgets to do the assignment. - // CHECK-NEXT: call + // CHECK-NEXT: call {{.*}}void ((a=a),a); // Not a use. gcc gets this wrong, it doesn't emit the copy! - // CHECK-NEXT: call + // CHECK-NEXT: call {{.*}}void (void)(a=a); // Not a use. gcc got this wrong in 4.2 and omitted the side effects diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp index 38c8829347c2d..f6ae0c525ab2a 100644 --- a/test/CodeGenCXX/volatile.cpp +++ b/test/CodeGenCXX/volatile.cpp @@ -15,7 +15,7 @@ namespace test0 { void test(A t) { // CHECK: [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8 // CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0 - // CHECK-NEXT: [[TMP:%.*]] = call [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* [[T:%.*]]) + // CHECK-NEXT: [[TMP:%.*]] = call dereferenceable({{[0-9]+}}) [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* dereferenceable({{[0-9]+}}) [[T:%.*]]) // CHECK-NEXT: ret void array[0] = t; } diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index 282bd2a172ad6..e07d48463f4f8 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -35,7 +35,7 @@ void g() { // updated correctly. // CHECK-TEST2: @_ZTSN5Test21AE = constant -// CHECK-TEST2: @_ZTIN5Test21AE = unnamed_addr constant +// CHECK-TEST2: @_ZTIN5Test21AE = constant // CHECK-TEST2: @_ZTVN5Test21AE = unnamed_addr constant namespace Test2 { struct A { diff --git a/test/CodeGenCXX/vtable-cast-crash.cpp b/test/CodeGenCXX/vtable-cast-crash.cpp index cc419fd4f522d..58f9e0bf8f768 100644 --- a/test/CodeGenCXX/vtable-cast-crash.cpp +++ b/test/CodeGenCXX/vtable-cast-crash.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only %s +// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s struct A { A(); diff --git a/test/CodeGenCXX/vtable-key-function-arm.cpp b/test/CodeGenCXX/vtable-key-function-arm.cpp index 08efe8a141ea6..6f1265b6277d4 100644 --- a/test/CodeGenCXX/vtable-key-function-arm.cpp +++ b/test/CodeGenCXX/vtable-key-function-arm.cpp @@ -4,7 +4,7 @@ // The 'a' variants ask for the v-table first. // The 'b' variants ask for the v-table second. // The 'c' variants ask for the v-table third. -// We do a separate CHECK-LATE pass because the RTTI defintion gets +// We do a separate CHECK-LATE pass because the RTTI definition gets // changed after the fact, which causes reordering of the globals. // These are not separated into namespaces because the way that Sema @@ -91,7 +91,7 @@ struct Test2a { Test2a::Test2a() { use(typeid(Test2a)); } // CHECK: @_ZTV6Test2a = unnamed_addr constant // CHECK-LATE: @_ZTS6Test2a = constant -// CHECK-LATE: @_ZTI6Test2a = unnamed_addr constant +// CHECK-LATE: @_ZTI6Test2a = constant // 'bar' becomes the key function when 'foo' is defined inline. void Test2a::bar() {} @@ -112,7 +112,7 @@ void Test2b::bar() {} Test2b::Test2b() { use(typeid(Test2b)); } // CHECK: @_ZTV6Test2b = unnamed_addr constant // CHECK-LATE: @_ZTS6Test2b = constant -// CHECK-LATE: @_ZTI6Test2b = unnamed_addr constant +// CHECK-LATE: @_ZTI6Test2b = constant inline void Test2b::foo() {} @@ -132,7 +132,7 @@ inline void Test2c::foo() {} Test2c::Test2c() { use(typeid(Test2c)); } // CHECK: @_ZTV6Test2c = unnamed_addr constant // CHECK: @_ZTS6Test2c = constant -// CHECK: @_ZTI6Test2c = unnamed_addr constant +// CHECK: @_ZTI6Test2c = constant /*** Test3a ******************************************************************/ @@ -146,7 +146,7 @@ struct Test3a { Test3a::Test3a() { use(typeid(Test3a)); } // CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant // There ceases to be a key function after these declarations. inline void Test3a::bar() {} @@ -167,7 +167,7 @@ inline void Test3b::bar() {} Test3b::Test3b() { use(typeid(Test3b)); } // CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant inline void Test3b::foo() {} @@ -187,7 +187,7 @@ inline void Test3c::foo() {} Test3c::Test3c() { use(typeid(Test3c)); } // CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test3c = linkonce_odr constant -// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test3c = linkonce_odr constant /*** Test4a ******************************************************************/ @@ -201,7 +201,7 @@ template <class T> struct Test4a { template <> Test4a<int>::Test4a() { use(typeid(Test4a)); } // CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test4aIiE = linkonce_odr constant -// CHECK: @_ZTI6Test4aIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test4aIiE = linkonce_odr constant // There ceases to be a key function after these declarations. template <> inline void Test4a<int>::bar() {} @@ -222,7 +222,7 @@ template <> inline void Test4b<int>::bar() {} template <> Test4b<int>::Test4b() { use(typeid(Test4b)); } // CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test4bIiE = linkonce_odr constant -// CHECK: @_ZTI6Test4bIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test4bIiE = linkonce_odr constant template <> inline void Test4b<int>::foo() {} @@ -242,7 +242,7 @@ template <> inline void Test4c<int>::foo() {} template <> Test4c<int>::Test4c() { use(typeid(Test4c)); } // CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test4cIiE = linkonce_odr constant -// CHECK: @_ZTI6Test4cIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test4cIiE = linkonce_odr constant /*** Test5a ******************************************************************/ @@ -259,7 +259,7 @@ template <> inline void Test5a<int>::foo(); template <> Test5a<int>::Test5a() { use(typeid(Test5a)); } // CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test5aIiE = linkonce_odr constant -// CHECK: @_ZTI6Test5aIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test5aIiE = linkonce_odr constant // There ceases to be a key function after these declarations. template <> inline void Test5a<int>::bar() {} @@ -281,7 +281,7 @@ template <> inline void Test5b<int>::bar() {} template <> Test5b<int>::Test5b() { use(typeid(Test5b)); } // CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test5bIiE = linkonce_odr constant -// CHECK: @_ZTI6Test5bIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test5bIiE = linkonce_odr constant template <> inline void Test5a<int>::foo(); template <> inline void Test5b<int>::foo() {} @@ -304,4 +304,4 @@ template <> inline void Test5c<int>::foo() {} template <> Test5c<int>::Test5c() { use(typeid(Test5c)); } // CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test5cIiE = linkonce_odr constant -// CHECK: @_ZTI6Test5cIiE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test5cIiE = linkonce_odr constant diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp index bcd3e889d2ef9..bf2e1f9720b50 100644 --- a/test/CodeGenCXX/vtable-key-function-ios.cpp +++ b/test/CodeGenCXX/vtable-key-function-ios.cpp @@ -4,7 +4,7 @@ // The 'a' variants ask for the v-table first. // The 'b' variants ask for the v-table second. // The 'c' variants ask for the v-table third. -// We do a separate CHECK-LATE pass because the RTTI defintion gets +// We do a separate CHECK-LATE pass because the RTTI definition gets // changed after the fact, which causes reordering of the globals. // These are not separated into namespaces because the way that Sema @@ -59,7 +59,7 @@ struct Test1a { Test1a::Test1a() { use(typeid(Test1a)); } // CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test1a = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test1a = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test1a = linkonce_odr constant // This defines the key function. inline void Test1a::foo() {} @@ -79,7 +79,7 @@ inline void Test1b::foo() {} Test1b::Test1b() { use(typeid(Test1b)); } // CHECK: @_ZTV6Test1b = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test1b = linkonce_odr constant -// CHECK: @_ZTI6Test1b = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test1b = linkonce_odr constant /*** Test2a ******************************************************************/ @@ -93,7 +93,7 @@ struct Test2a { Test2a::Test2a() { use(typeid(Test2a)); } // CHECK: @_ZTV6Test2a = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test2a = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test2a = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test2a = linkonce_odr constant void Test2a::bar() {} inline void Test2a::foo() {} @@ -112,7 +112,7 @@ void Test2b::bar() {} Test2b::Test2b() { use(typeid(Test2b)); } // CHECK: @_ZTV6Test2b = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test2b = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test2b = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test2b = linkonce_odr constant inline void Test2b::foo() {} @@ -131,7 +131,7 @@ inline void Test2c::foo() {} Test2c::Test2c() { use(typeid(Test2c)); } // CHECK: @_ZTV6Test2c = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test2c = linkonce_odr constant -// CHECK: @_ZTI6Test2c = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test2c = linkonce_odr constant /*** Test3a ******************************************************************/ @@ -145,7 +145,7 @@ struct Test3a { Test3a::Test3a() { use(typeid(Test3a)); } // CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant // This defines the key function. inline void Test3a::bar() {} @@ -165,7 +165,7 @@ inline void Test3b::bar() {} Test3b::Test3b() { use(typeid(Test3b)); } // CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant // CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant -// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant +// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant // This defines the key function. inline void Test3b::foo() {} @@ -186,4 +186,4 @@ inline void Test3c::foo() {} Test3c::Test3c() { use(typeid(Test3c)); } // CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant // CHECK: @_ZTS6Test3c = linkonce_odr constant -// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI6Test3c = linkonce_odr constant diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp index 8f084a9c5b7bd..b8ac6f512b48a 100644 --- a/test/CodeGenCXX/vtable-layout-abi-examples.cpp +++ b/test/CodeGenCXX/vtable-layout-abi-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts > %t 2>&1 +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts > %t 2>/dev/null // RUN: FileCheck --check-prefix=CHECK-1 %s < %t // RUN: FileCheck --check-prefix=CHECK-2 %s < %t // RUN: FileCheck --check-prefix=CHECK-3 %s < %t diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index c17e33387e52f..9c08b3037ca1a 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -1,8 +1,6 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt // RUN: FileCheck --check-prefix=CHECK %s < %t -// RUN: FileCheck --check-prefix=CHECK-HIDDEN %s < %t.hidden // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt namespace { @@ -93,57 +91,47 @@ void use_F() { // and hidden visibility (rdar://problem/7523229). // CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant // CHECK-DAG: @_ZTS1C = linkonce_odr constant -// CHECK-DAG: @_ZTI1C = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1C = linkonce_odr constant // CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTV1C = linkonce_odr hidden unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTS1C = linkonce_odr constant -// CHECK-HIDDEN-DAG: @_ZTI1C = linkonce_odr hidden unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTT1C = linkonce_odr hidden unnamed_addr constant // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. // CHECK-DAG: @_ZTV1D = unnamed_addr constant // CHECK-DAG: @_ZTS1D = constant -// CHECK-DAG: @_ZTI1D = unnamed_addr constant +// CHECK-DAG: @_ZTI1D = constant // E<char> is an explicit specialization with a key function defined // in this translation unit, so its vtable should have external // linkage. // CHECK-DAG: @_ZTV1EIcE = unnamed_addr constant // CHECK-DAG: @_ZTS1EIcE = constant -// CHECK-DAG: @_ZTI1EIcE = unnamed_addr constant +// CHECK-DAG: @_ZTI1EIcE = constant // E<short> is an explicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. // CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant // CHECK-DAG: @_ZTS1EIsE = weak_odr constant -// CHECK-DAG: @_ZTI1EIsE = weak_odr unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTS1EIsE = weak_odr constant -// CHECK-HIDDEN-DAG: @_ZTI1EIsE = weak_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1EIsE = weak_odr constant // F<short> is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage // CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant // CHECK-DAG: @_ZTS1FIsE = weak_odr constant -// CHECK-DAG: @_ZTI1FIsE = weak_odr unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant -// CHECK-HIDDEN-DAG: @_ZTS1FIsE = weak_odr constant -// CHECK-HIDDEN-DAG: @_ZTI1FIsE = weak_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1FIsE = weak_odr constant // E<long> is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // linkonce_odr linkage. // CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant // CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant -// CHECK-DAG: @_ZTI1EIlE = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant // F<long> is an implicit template instantiation with no key function, // so its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant // CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant -// CHECK-DAG: @_ZTI1FIlE = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant // F<int> is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. @@ -160,19 +148,19 @@ void use_F() { // internal linkage. // CHECK-DAG: @"_ZTV3$_0" = internal unnamed_addr constant // CHECK-DAG: @"_ZTS3$_0" = internal constant -// CHECK-DAG: @"_ZTI3$_0" = internal unnamed_addr constant +// CHECK-DAG: @"_ZTI3$_0" = internal constant // The A vtable should have internal linkage since it is inside an anonymous // namespace. // CHECK-DAG: @_ZTVN12_GLOBAL__N_11AE = internal unnamed_addr constant // CHECK-DAG: @_ZTSN12_GLOBAL__N_11AE = internal constant -// CHECK-DAG: @_ZTIN12_GLOBAL__N_11AE = internal unnamed_addr constant +// CHECK-DAG: @_ZTIN12_GLOBAL__N_11AE = internal constant // F<char> is an explicit specialization without a key function, so // its vtable should have linkonce_odr linkage. // CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant // CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant -// CHECK-DAG: @_ZTI1FIcE = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant // CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant template <typename T> diff --git a/test/CodeGenCXX/weak-extern-typeinfo.cpp b/test/CodeGenCXX/weak-extern-typeinfo.cpp index 3c3406e55970c..38f6a3e462330 100644 --- a/test/CodeGenCXX/weak-extern-typeinfo.cpp +++ b/test/CodeGenCXX/weak-extern-typeinfo.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s // rdar://10246395 #define WEAK __attribute__ ((weak)) @@ -32,16 +32,16 @@ void V1::foo() { } void V2::foo() { } // CHECK: @_ZTS1A = weak_odr constant -// CHECK: @_ZTI1A = weak_odr unnamed_addr constant +// CHECK: @_ZTI1A = weak_odr constant // CHECK: @_ZTS1B = weak_odr constant -// CHECK: @_ZTI1B = weak_odr unnamed_addr constant +// CHECK: @_ZTI1B = weak_odr constant // CHECK: @_ZTS1C = weak_odr constant // CHECK: @_ZTS2T1 = linkonce_odr constant -// CHECK: @_ZTI2T1 = linkonce_odr unnamed_addr constant +// CHECK: @_ZTI2T1 = linkonce_odr constant // CHECK: @_ZTS1T = linkonce_odr constant -// CHECK: @_ZTI1T = linkonce_odr unnamed_addr constant -// CHECK: @_ZTI1C = weak_odr unnamed_addr constant +// CHECK: @_ZTI1T = linkonce_odr constant +// CHECK: @_ZTI1C = weak_odr constant // CHECK: @_ZTS2V1 = weak_odr constant -// CHECK: @_ZTI2V1 = weak_odr unnamed_addr constant +// CHECK: @_ZTI2V1 = weak_odr constant // CHECK: @_ZTS2V2 = weak_odr constant -// CHECK: @_ZTI2V2 = weak_odr unnamed_addr constant +// CHECK: @_ZTI2V2 = weak_odr constant diff --git a/test/CodeGenCXX/weak-external.cpp b/test/CodeGenCXX/weak-external.cpp index dad54f6861b0e..a2c53a59dcd59 100644 --- a/test/CodeGenCXX/weak-external.cpp +++ b/test/CodeGenCXX/weak-external.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fexceptions %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple %itanium_abi_triple %s -S -emit-llvm -o - | FileCheck %s // PR4262 // CHECK-NOT: _ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag diff --git a/test/CodeGenCXX/windows-itanium-exceptions.cpp b/test/CodeGenCXX/windows-itanium-exceptions.cpp new file mode 100644 index 0000000000000..e2c4190ac9f6b --- /dev/null +++ b/test/CodeGenCXX/windows-itanium-exceptions.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -emit-llvm -triple thumbv7-windows-itanium -fexceptions -fcxx-exceptions %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fexceptions -fcxx-exceptions %s -o - | FileCheck %s +// REQUIRES: asserts + +void except() { + throw 32; +} + +void attempt() { + try { except(); } catch (...) { } +} + +// CHECK: @_ZTIi = external constant i8* + +// CHECK: define {{.*}}void @_Z6exceptv() {{.*}} { +// CHECK: %exception = call {{.*}}i8* @__cxa_allocate_exception(i32 4) +// CHECK: %0 = bitcast i8* %exception to i32* +// CHECK: store i32 32, i32* %0 +// CHECK: call {{.*}}void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) +// CHECK: unreachable +// CHECK: } + +// CHECK: define {{.*}}void @_Z7attemptv() {{.*}} { +// CHECK: %exn.slot = alloca i8* +// CHECK: %ehselector.slot = alloca i32 +// CHECK: invoke {{.*}}void @_Z6exceptv() +// CHECK: to label %invoke.cont unwind label %lpad +// CHECK: invoke.cont: +// CHECK: br label %try.cont +// CHECK: lpad: +// CHECK: %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK: catch i8* null +// CHECK: %1 = extractvalue { i8*, i32 } %0, 0 +// CHECK: store i8* %1, i8** %exn.slot +// CHECK: %2 = extractvalue { i8*, i32 } %0, 1 +// CHECK: store i32 %2, i32* %ehselector.slot +// CHECK: br label %catch +// CHECK: catch: +// CHECK: %exn = load i8** %exn.slot +// CHECK: %3 = call {{.*}}i8* @__cxa_begin_catch(i8* %{{2|exn}}) +// CHECK: call {{.*}}void @__cxa_end_catch() +// CHECK: br label %try.cont +// CHECK: try.cont: +// CHECK: ret void +// CHECK: } + + |