diff options
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r-- | test/CodeGenCXX/constructor-init.cpp | 21 | ||||
-rw-r--r-- | test/CodeGenCXX/copy-constructor-synthesis.cpp | 54 | ||||
-rw-r--r-- | test/CodeGenCXX/member-expressions.cpp | 40 | ||||
-rw-r--r-- | test/CodeGenCXX/multi-dim-operator-new.cpp | 49 | ||||
-rw-r--r-- | test/CodeGenCXX/references.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/rtti-fundamental.cpp | 71 | ||||
-rw-r--r-- | test/CodeGenCXX/rtti-linkage.cpp | 1 | ||||
-rw-r--r-- | test/CodeGenCXX/template-instantiation.cpp | 76 | ||||
-rw-r--r-- | test/CodeGenCXX/temporaries.cpp | 13 | ||||
-rw-r--r-- | test/CodeGenCXX/thunks.cpp | 137 | ||||
-rw-r--r-- | test/CodeGenCXX/virt.cpp | 52 | ||||
-rw-r--r-- | test/CodeGenCXX/virtual-bases.cpp | 23 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout-abi-examples.cpp | 1 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout.cpp | 49 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-linkage.cpp | 20 |
15 files changed, 527 insertions, 88 deletions
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index a0a35fa16f1bd..284b8b5938f94 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -80,3 +80,24 @@ void f() { // CHECK-NOT: call void @_ZN1AIsED1Ev // CHECK: ret void } + +template<typename T> +struct X { + X(const X &); + + T *start; + T *end; +}; + +template<typename T> struct X; + +// Make sure that the instantiated constructor initializes start and +// end properly. +// CHECK: define linkonce_odr void @_ZN1XIiEC2ERKS0_ +// CHECK: {{store.*null}} +// CHECK: {{store.*null}} +// CHECK: ret +template<typename T> +X<T>::X(const X &other) : start(0), end(0) { } + +X<int> get_X(X<int> x) { return x; } diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index ae8eefa7fe40d..9cafd0accdb67 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -1,7 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s -// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s extern "C" int printf(...); @@ -24,6 +21,7 @@ struct P { }; +// CHECK: define linkonce_odr void @_ZN1XC1ERKS_ 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") {} @@ -113,10 +111,46 @@ void f(const B &b1) { B b2(b1); } -// CHECK-LP64: .globl __ZN1XC1ERKS_ -// CHECK-LP64: .weak_definition __ZN1XC1ERKS_ -// CHECK-LP64: __ZN1XC1ERKS_: +// PR6628 +namespace PR6628 { + +struct T { + T(); + ~T(); + + double d; +}; + +struct A { + A(const A &other, const T &t = T(), const T& t2 = T()); +}; + +struct B : A { + A a1; + A a2; + A a[10]; +}; + +// Force the copy constructor to be synthesized. +void f(B b1) { + B b2 = b1; +} + +// CHECK: define linkonce_odr void @_ZN6PR66281BC2ERKS0_ +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281AC2ERKS0_RKNS_1TES5_ +// CHECK: call void @_ZN6PR66281TD1Ev +// CHECK: call void @_ZN6PR66281TD1Ev +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281AC1ERKS0_RKNS_1TES5_ +// CHECK: call void @_ZN6PR66281TD1Ev +// CHECK: call void @_ZN6PR66281TD1Ev +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281TC1Ev +// CHECK: call void @_ZN6PR66281AC1ERKS0_RKNS_1TES5_ +// CHECK: call void @_ZN6PR66281TD1Ev +// CHECK: call void @_ZN6PR66281TD1Ev +} -// CHECK-LP32: .globl __ZN1XC1ERKS_ -// CHECK-LP32: .weak_definition __ZN1XC1ERKS_ -// CHECK-LP32: __ZN1XC1ERKS_: diff --git a/test/CodeGenCXX/member-expressions.cpp b/test/CodeGenCXX/member-expressions.cpp index 720a9a70d07bb..d9fb3940b05b0 100644 --- a/test/CodeGenCXX/member-expressions.cpp +++ b/test/CodeGenCXX/member-expressions.cpp @@ -44,3 +44,43 @@ int f() { return A().foo(); } } + +namespace test4 { + struct A { + int x; + }; + struct B { + int x; + void foo(); + }; + struct C : A, B { + }; + + extern C *c_ptr; + + // CHECK: define i32 @_ZN5test44testEv() + int test() { + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @_ZN5test41B3fooEv + c_ptr->B::foo(); + + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store i32 5 + c_ptr->B::x = 5; + + // CHECK: load {{.*}} @_ZN5test45c_ptrE + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: load i32* + return c_ptr->B::x; + } +} diff --git a/test/CodeGenCXX/multi-dim-operator-new.cpp b/test/CodeGenCXX/multi-dim-operator-new.cpp new file mode 100644 index 0000000000000..7a235e83a78da --- /dev/null +++ b/test/CodeGenCXX/multi-dim-operator-new.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s +// PR6641 + +extern "C" int printf(const char *, ...); + +struct Foo { + Foo() : iFoo (2) { + printf("%p\n", this); + } + int iFoo; +}; + + +typedef Foo (*T)[3][4]; + +T bar() { + return new Foo[2][3][4]; +} + +T bug(int i) { + return new Foo[i][3][4]; +} + +void pr(T a) { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 4; j++) + printf("%p\n", a[i][j]); +} + +Foo *test() { + return new Foo[5]; +} + +int main() { + T f = bar(); + pr(f); + f = bug(3); + pr(f); + + Foo * g = test(); + for (int i = 0; i < 5; i++) + printf("%d\n", g[i].iFoo); + return 0; +} + +// CHECK: call noalias i8* @_Znam +// CHECK: call noalias i8* @_Znam +// CHECK: call noalias i8* @_Znam + diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 39b5909fb9a4f..5a5947dd81624 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -147,3 +147,11 @@ void f(int &a) { struct s0; struct s1 { struct s0 &s0; }; void f0(s1 a) { s1 b = a; } + +// PR6024 +// CHECK: @_Z2f2v() +// CHECK: alloca +// CHECK: store +// CHECK: load +// CHECK: ret +const int &f2() { return 0; } diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp new file mode 100644 index 0000000000000..473f48db67add --- /dev/null +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +#include <typeinfo> + +std::type_info foo() { + return typeid(void); +} + +namespace __cxxabiv1 { + struct __fundamental_type_info { + virtual ~__fundamental_type_info() {} + }; +} + +// CHECK: @_ZTIv = weak_odr constant +// CHECK: @_ZTIPv = weak_odr constant +// CHECK: @_ZTIPKv = weak_odr constant +// CHECK: @_ZTIDi = weak_odr constant +// CHECK: @_ZTIPDi = weak_odr constant +// CHECK: @_ZTIPKDi = weak_odr constant +// CHECK: @_ZTIDs = weak_odr constant +// CHECK: @_ZTIPDs = weak_odr constant +// CHECK: @_ZTIPKDs = weak_odr constant +// CHECK: @_ZTIy = weak_odr constant +// CHECK: @_ZTIPy = weak_odr constant +// CHECK: @_ZTIPKy = weak_odr constant +// CHECK: @_ZTIx = weak_odr constant +// CHECK: @_ZTIPx = weak_odr constant +// CHECK: @_ZTIPKx = weak_odr constant +// CHECK: @_ZTIw = weak_odr constant +// CHECK: @_ZTIPw = weak_odr constant +// CHECK: @_ZTIPKw = weak_odr constant +// CHECK: @_ZTIt = weak_odr constant +// CHECK: @_ZTIPt = weak_odr constant +// CHECK: @_ZTIPKt = weak_odr constant +// CHECK: @_ZTIs = weak_odr constant +// CHECK: @_ZTIPs = weak_odr constant +// CHECK: @_ZTIPKs = weak_odr constant +// CHECK: @_ZTIm = weak_odr constant +// CHECK: @_ZTIPm = weak_odr constant +// CHECK: @_ZTIPKm = weak_odr constant +// CHECK: @_ZTIl = weak_odr constant +// CHECK: @_ZTIPl = weak_odr constant +// CHECK: @_ZTIPKl = weak_odr constant +// CHECK: @_ZTIj = weak_odr constant +// CHECK: @_ZTIPj = weak_odr constant +// CHECK: @_ZTIPKj = weak_odr constant +// CHECK: @_ZTIi = weak_odr constant +// CHECK: @_ZTIPi = weak_odr constant +// CHECK: @_ZTIPKi = weak_odr constant +// CHECK: @_ZTIh = weak_odr constant +// CHECK: @_ZTIPh = weak_odr constant +// CHECK: @_ZTIPKh = weak_odr constant +// CHECK: @_ZTIf = weak_odr constant +// CHECK: @_ZTIPf = weak_odr constant +// CHECK: @_ZTIPKf = weak_odr constant +// CHECK: @_ZTIe = weak_odr constant +// CHECK: @_ZTIPe = weak_odr constant +// CHECK: @_ZTIPKe = weak_odr constant +// CHECK: @_ZTId = weak_odr constant +// CHECK: @_ZTIPd = weak_odr constant +// CHECK: @_ZTIPKd = weak_odr constant +// CHECK: @_ZTIc = weak_odr constant +// CHECK: @_ZTIPc = weak_odr constant +// CHECK: @_ZTIPKc = weak_odr constant +// CHECK: @_ZTIb = weak_odr constant +// CHECK: @_ZTIPb = weak_odr constant +// CHECK: @_ZTIPKb = weak_odr constant +// CHECK: @_ZTIa = weak_odr constant +// CHECK: @_ZTIPa = weak_odr constant +// CHECK: @_ZTIPKa = weak_odr constant diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index 799c1d41c7261..b9eb5b4ad4113 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -92,6 +92,7 @@ const std::type_info &t2() { (void)typeid(D *); (void)typeid(D (*)()); (void)typeid(void (*)(D)); + (void)typeid(void (*)(D&)); // The exception specification is not part of the RTTI descriptor, so it should not have // internal linkage. (void)typeid(void (*)() throw (D)); diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp new file mode 100644 index 0000000000000..416c0a1a20729 --- /dev/null +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant +// CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE +// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = constant + +// CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev( +// CHECK: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_( +// CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd( + +namespace test0 { + struct basic_streambuf { + virtual ~basic_streambuf(); + }; + template<typename _CharT > + struct stdio_sync_filebuf : public basic_streambuf { + 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() { + } + extern template class stdio_sync_filebuf<wchar_t>; +} + +namespace test1 { + struct basic_streambuf { + virtual ~basic_streambuf(); + }; + template<typename _CharT > + struct stdio_sync_filebuf : public basic_streambuf { + virtual void xsgetn(); + }; + + // Just a declaration should not force the vtable to be emitted. + template<> void stdio_sync_filebuf<wchar_t>::xsgetn(); +} + +namespace test2 { + template<typename T1> + class C { + virtual ~C(); + void zedbar(double) { + } + template<typename T2> + void foobar(T2 foo) { + } + }; + extern template class C<int>; + void g() { + // The extern template declaration should not prevent us from producing + // the implicit constructor (test at the top). + C<int> a; + + // or foobar(test at the top). + a.foobar(0.0); + + // But it should prevent zebbar + // (test at the top). + a.zedbar(0.0); + } +} + +namespace test3 { + template<typename T> + class basic_fstreamXX { + virtual void foo(){} + virtual void is_open() const { } + }; + + extern template class basic_fstreamXX<char>; + // This template instantiation should not cause us to produce a vtable. + // (test at the top). + template void basic_fstreamXX<char>::is_open() const; +} diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index cd0cf77f53b2d..4aad3c0056ca0 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -288,3 +288,16 @@ void g() { } } + +namespace PR6648 { + struct B { + ~B(); + }; + B foo; + struct D; + D& zed(B); + void foobar() { + // CHECK: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE + zed(foo); + } +} diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp new file mode 100644 index 0000000000000..b91ba3239b1e1 --- /dev/null +++ b/test/CodeGenCXX/thunks.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +namespace Test1 { + +// Check that we emit a non-virtual thunk for C::f. + +struct A { + virtual void f(); +}; + +struct B { + virtual void f(); +}; + +struct C : A, B { + virtual void c(); + + virtual void f(); +}; + +// CHECK: define void @_ZThn8_N5Test11C1fEv( +void C::f() { } + +} + +namespace Test2 { + +// Check that we emit a thunk for B::f since it's overriding a virtual base. + +struct A { + virtual void f(); +}; + +struct B : virtual A { + virtual void b(); + virtual void f(); +}; + +// CHECK: define void @_ZTv0_n24_N5Test21B1fEv( +void B::f() { } + +} + +namespace Test3 { + +// Check that we emit a covariant thunk for B::f. + +struct V1 { }; +struct V2 : virtual V1 { }; + +struct A { + virtual V1 *f(); +}; + +struct B : A { + virtual void b(); + + virtual V2 *f(); +}; + +// CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv( +V2 *B::f() { return 0; } + +} + +namespace Test4 { + +// Check that the thunk for 'C::f' has the same visibility as the function itself. + +struct A { + virtual void f(); +}; + +struct B { + virtual void f(); +}; + +struct __attribute__((visibility("protected"))) C : A, B { + virtual void c(); + + virtual void f(); +}; + +// CHECK: define protected void @_ZThn8_N5Test41C1fEv( +void C::f() { } + +} + +// This is from Test5: +// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv + +// Check that the thunk gets internal linkage. +namespace { + +struct A { + virtual void f(); +}; + +struct B { + virtual void f(); +}; + +struct C : A, B { + virtual void c(); + + virtual void f(); +}; + +// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( +void C::f() { } + +} + +// Force C::f to be used. +void f() { + C c; + + c.f(); +} + +namespace Test5 { + +// Check that the thunk for 'B::f' gets the same linkage as the function itself. +struct A { + virtual void f(); +}; + +struct B : virtual A { + virtual void f() { } +}; + +void f(B b) { + b.f(); +} +} + + diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 9d671c4e5f0ef..c40412963097d 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -693,55 +693,3 @@ void test12_foo() { // CHECK-LPLL64: call void % // CHECK-LPLL64: call void @_ZN8test12_A3fooEv(%class.test14* %{{.*}}) - -// FIXME: This is the wrong thunk, but until these issues are fixed, better -// than nothing. -// CHECK-LPLL64define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) -// CHECK-LPLL64 %{{retval|2}} = alloca %class.test8_D* -// CHECK-LPLL64 %.addr = alloca %class.test8_D* -// CHECK-LPLL64 store %class.test8_D* %0, %class.test8_D** %.addr -// CHECK-LPLL64 %{{this|3}} = load %class.test8_D** %.addr -// CHECK-LPLL64 %{{1|4}} = bitcast %class.test8_D* %{{this|3}} to i8* -// CHECK-LPLL64 %{{2|5}} = getelementptr inbounds i8* %{{1|4}}, i64 -16 -// CHECK-LPLL64 %{{3|6}} = bitcast i8* %{{2|5}} to %class.test8_D* -// CHECK-LPLL64 %{{4|7}} = bitcast %class.test8_D* %{{3|6}} to i8* -// CHECK-LPLL64 %{{5|8}} = bitcast %class.test8_D* %3 to i64** -// CHECK-LPLL64 %{{vtable|9}} = load i64** %{{5|8}} -// CHECK-LPLL64 %{{6|10}} = getelementptr inbounds i64* %{{vtable|9}}, i64 -9 -// CHECK-LPLL64 %{{7|11}} = load i64* %{{6|10}} -// CHECK-LPLL64 %{{8|12}} = getelementptr i8* %{{4|7}}, i64 %{{7|11}} -// CHECK-LPLL64 %{{9|13}} = bitcast i8* %{{8|12}} to %class.test8_D* -// CHECK-LPLL64 %{{call|14}} = call %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D* %{{9|13}}) -// CHECK-LPLL64 store %class.test8_D* %{{call|14}}, %class.test8_D** %{{retval|2}} -// CHECK-LPLL64 %{{10|15}} = load %class.test8_D** %{{retval|2}} -// CHECK-LPLL64 ret %class.test8_D* %{{10|15}} -// CHECK-LPLL64} - -// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%{{class.test8_D|.*}}*) -// CHECK-LPLL64: %{{retval|1}} = alloca %class.test8_D* -// CHECK-LPLL64: %{{.addr|2}} = alloca %class.test8_D* -// CHECK-LPLL64: store %class.test8_D* %0, %class.test8_D** %{{.addr|2}} -// CHECK-LPLL64: %{{this|3}} = load %class.test8_D** %{{.addr|2}} -// CHECK-LPLL64: %{{call|4}} = call %class.test8_D* @_ZN8test16_D4foo1Ev(%class.test8_D* %{{this|3}}) -// CHECK-LPLL64: %{{1|5}} = icmp ne %class.test8_D* %{{call|4}}, null -// CHECK-LPLL64: br i1 %{{1|5}}, label %{{2|6}}, label %{{12|17}} -// CHECK-LPLL64:; <label>:{{2|6}} -// CHECK-LPLL64: %{{3|7}} = bitcast %class.test8_D* %{{call|4}} to i8* -// CHECK-LPLL64: %{{4|8}} = getelementptr inbounds i8* %{{3|7}}, i64 16 -// CHECK-LPLL64: %{{5|9}} = bitcast i8* %4 to %class.test8_D* -// CHECK-LPLL64: %{{6|10}} = bitcast %class.test8_D* %{{5|9}} to i8* -// CHECK-LPLL64: %{{7|11}} = bitcast %class.test8_D* %{{5|9}} to i64** -// CHECK-LPLL64: %{{vtable|12}} = load i64** %{{7|11}} -// CHECK-LPLL64: %{{8|13}} = getelementptr inbounds i64* %vtable, i64 -4 -// CHECK-LPLL64: %{{9|14}} = load i64* %{{8|13}} -// CHECK-LPLL64: %{{10|15}} = getelementptr i8* %{{6|10}}, i64 %{{9|14}} -// CHECK-LPLL64: %{{11|16}} = bitcast i8* %{{10|15}} to %class.test8_D* -// CHECK-LPLL64: br label %{{13|18}} -// CHECK-LPLL64:; <label>:{{12|17}} -// CHECK-LPLL64: br label %{{13|18}} -// CHECK-LPLL64:; <label>:{{13|18}} -// CHECK-LPLL64: %{{14|19}} = phi %class.test8_D* [ %{{11|16}}, %{{2|6}} ], [ %{{call|4}}, %{{12|17}} ] -// CHECK-LPLL64: store %class.test8_D* %{{14|19}}, %class.test8_D** %{{retval|2}} -// CHECK-LPLL64: %{{15|20}} = load %class.test8_D** %{{retval|2}} -// CHECK-LPLL64: ret %class.test8_D* %{{15|20}} -// CHECK-LPLL64:} diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 627717576302e..61de3153fd509 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -23,3 +23,26 @@ struct C : virtual A { // CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext) // CHECK: define void @_ZN1CC2Eb(%struct.B* %this, i8** %vtt, i1 zeroext) C::C(bool) { } + +// PR6251 +namespace PR6251 { + +// Test that we don't call the A<char> constructor twice. + +template<typename T> +struct A { A(); }; + +struct B : virtual A<char> { }; +struct C : virtual A<char> { }; + +struct D : B, C { + D(); +}; + +// CHECK: define void @_ZN6PR62511DC1Ev +// CHECK: call void @_ZN6PR62511AIcEC2Ev +// CHECK-NOT: call void @_ZN6PR62511AIcEC2Ev +// CHECK: ret void +D::D() { } + +} diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp index a82fca736c79d..c01c5ef72cc52 100644 --- a/test/CodeGenCXX/vtable-layout-abi-examples.cpp +++ b/test/CodeGenCXX/vtable-layout-abi-examples.cpp @@ -178,7 +178,6 @@ struct C : virtual public A { int j; }; // CHECK-NEXT: 7 | vcall_offset (-16) // CHECK-NEXT: 8 | offset_to_top (-16) // CHECK-NEXT: 9 | Test2::D RTTI -// CHECK-NEXT: -- (Test2::A, 16) vtable address -- // CHECK-NEXT: -- (Test2::C, 16) vtable address -- // CHECK-NEXT: 10 | [unused] void Test2::A::f() struct D : public B, public C { diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index bc3d54b8e4a7b..3a0dae41c3b06 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -635,7 +635,6 @@ struct D : virtual B, virtual C { virtual void f(); }; // CHECK-NEXT: 9 | vcall_offset (-8) // CHECK-NEXT: 10 | offset_to_top (-8) // CHECK-NEXT: 11 | Test17::E RTTI -// CHECK-NEXT: -- (Test17::A, 8) vtable address -- // CHECK-NEXT: -- (Test17::C, 8) vtable address -- // CHECK-NEXT: 12 | void Test17::E::f() // CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] @@ -693,7 +692,6 @@ struct C : A, B { // CHECK-NEXT: 19 | vcall_offset (-16) // CHECK-NEXT: 20 | offset_to_top (-16) // CHECK-NEXT: 21 | Test18::D RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 22 | void Test18::D::f() // CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] @@ -725,7 +723,6 @@ struct C : A, B { // CHECK-NEXT: 9 | vcall_offset (0) // CHECK-NEXT: 10 | offset_to_top (-8) // CHECK-NEXT: 11 | Test18::C RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 12 | void Test18::B::f() // CHECK-NEXT: 13 | [unused] void Test18::C::g() @@ -745,7 +742,6 @@ struct C : A, B { // CHECK-NEXT: 2 | vcall_offset (0) // CHECK-NEXT: 3 | offset_to_top (0) // CHECK-NEXT: 4 | Test18::B RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 5 | void Test18::B::f() // CHECK-NEXT: 6 | [unused] void Test18::A::g() @@ -881,9 +877,6 @@ class E : virtual C { }; // CHECK-NEXT: 12 | vcall_offset (-8) // CHECK-NEXT: 13 | offset_to_top (-8) // CHECK-NEXT: 14 | Test21::F RTTI -// CHECK-NEXT: -- (Test21::A, 8) vtable address -- -// CHECK-NEXT: -- (Test21::B, 8) vtable address -- -// CHECK-NEXT: -- (Test21::C, 8) vtable address -- // CHECK-NEXT: -- (Test21::E, 8) vtable address -- // CHECK-NEXT: 15 | [unused] void Test21::F::f() // @@ -1012,7 +1005,6 @@ struct C : virtual A { }; // CHECK-NEXT: 6 | vcall_offset (-8) // CHECK-NEXT: 7 | offset_to_top (-8) // CHECK-NEXT: 8 | Test24::D RTTI -// CHECK-NEXT: -- (Test24::A, 8) vtable address -- // CHECK-NEXT: -- (Test24::C, 8) vtable address -- // CHECK-NEXT: 9 | [unused] void Test24::D::f() @@ -1030,14 +1022,13 @@ struct C : virtual A { }; // CHECK-NEXT: 1 | vcall_offset (-8) // CHECK-NEXT: 2 | offset_to_top (0) // CHECK-NEXT: 3 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::A, 8) vtable address -- // CHECK-NEXT: -- (Test24::C, 8) vtable address -- // CHECK-NEXT: 4 | [unused] void Test24::A::f() // CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (8) -// CHECK-NEXT: 7 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::A, 0) vtable address -- -// CHECK-NEXT: 8 | void Test24::A::f() +// CHECK-NEXT: 6 | offset_to_top (8) +// CHECK-NEXT: 7 | Test24::C RTTI +// CHECK-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-NEXT: 8 | void Test24::A::f() struct D : B, C { virtual void f(); }; @@ -1071,7 +1062,6 @@ struct B : virtual V { }; // CHECK-NEXT: 8 | offset_to_top (-8) // CHECK-NEXT: 9 | Test25::C RTTI // CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: -- (Test25::V, 8) vtable address -- // CHECK-NEXT: 10 | [unused] void Test25::V::f() // CHECK: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries). @@ -1089,7 +1079,6 @@ struct B : virtual V { }; // CHECK-NEXT: 2 | offset_to_top (0) // CHECK-NEXT: 3 | Test25::B RTTI // CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: -- (Test25::V, 8) vtable address -- // CHECK-NEXT: 4 | [unused] void Test25::V::f() // CHECK-NEXT: 5 | vcall_offset (0) // CHECK-NEXT: 6 | offset_to_top (8) @@ -1284,3 +1273,33 @@ struct E : D { void E::e() { } } + +namespace Test29 { + +// Test that the covariant return thunk for B::f will have a virtual 'this' adjustment, +// matching gcc. + +struct V1 { }; +struct V2 : virtual V1 { }; + +struct A { + virtual V1 *f(); +}; + +// CHECK: Vtable for 'Test29::B' (6 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test29::B RTTI +// CHECK-NEXT: -- (Test29::A, 0) vtable address -- +// CHECK-NEXT: -- (Test29::B, 0) vtable address -- +// CHECK-NEXT: 4 | Test29::V2 *Test29::B::f() +// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 5 | Test29::V2 *Test29::B::f() +struct B : virtual A { + virtual V2 *f(); +}; +V2 *B::f() { return 0; } + +} diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 63e17431c467a..a4ea2a19c2380 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -84,54 +84,54 @@ void use_F(F<char> &fc) { // CHECK: @_ZTV1B = external constant // C has no key function, so its vtable should have weak_odr linkage. +// CHECK: @_ZTV1C = weak_odr constant // CHECK: @_ZTS1C = weak_odr constant // CHECK: @_ZTI1C = weak_odr constant -// CHECK: @_ZTV1C = weak_odr constant // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. +// CHECK: @_ZTV1D = constant // CHECK: @_ZTS1D = constant // CHECK: @_ZTI1D = constant -// CHECK: @_ZTV1D = constant // E<char> is an explicit specialization with a key function defined // in this translation unit, so its vtable should have external // linkage. +// CHECK: @_ZTV1EIcE = constant // CHECK: @_ZTS1EIcE = constant // CHECK: @_ZTI1EIcE = constant -// CHECK: @_ZTV1EIcE = 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: @_ZTV1EIsE = weak_odr constant // CHECK: @_ZTS1EIsE = weak_odr constant // CHECK: @_ZTI1EIsE = weak_odr constant -// CHECK: @_ZTV1EIsE = weak_odr constant // F<short> is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage +// CHECK: @_ZTV1FIsE = weak_odr constant // CHECK: @_ZTS1FIsE = weak_odr constant // CHECK: @_ZTI1FIsE = weak_odr constant -// CHECK: @_ZTV1FIsE = weak_odr constant // E<long> is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. +// CHECK: @_ZTV1EIlE = weak_odr constant // CHECK: @_ZTS1EIlE = weak_odr constant // CHECK: @_ZTI1EIlE = weak_odr constant -// CHECK: @_ZTV1EIlE = weak_odr constant // F<long> is an implicit template instantiation with no key function, // so its vtable should have weak_odr linkage. +// CHECK: @_ZTV1FIlE = weak_odr constant // CHECK: @_ZTS1FIlE = weak_odr constant // CHECK: @_ZTI1FIlE = weak_odr constant -// CHECK: @_ZTV1FIlE = weak_odr constant // F<int> is an explicit template instantiation declaration without a // key function, so its vtable should have weak_odr linkage. +// CHECK: @_ZTV1FIiE = weak_odr constant // CHECK: @_ZTS1FIiE = weak_odr constant // CHECK: @_ZTI1FIiE = weak_odr constant -// CHECK: @_ZTV1FIiE = weak_odr constant // E<int> is an explicit template instantiation declaration. It has a // key function that is not instantiated, so we should only reference @@ -140,14 +140,14 @@ void use_F(F<char> &fc) { // The anonymous struct for e has no linkage, so the vtable should have // internal linkage. +// CHECK: @"_ZTV3$_0" = internal constant // CHECK: @"_ZTS3$_0" = internal constant // CHECK: @"_ZTI3$_0" = internal constant -// CHECK: @"_ZTV3$_0" = internal constant // The A vtable should have internal linkage since it is inside an anonymous // namespace. +// CHECK: @_ZTVN12_GLOBAL__N_11AE = internal constant // CHECK: @_ZTSN12_GLOBAL__N_11AE = internal constant // CHECK: @_ZTIN12_GLOBAL__N_11AE = internal constant -// CHECK: @_ZTVN12_GLOBAL__N_11AE = internal constant |