diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
| commit | ecb7e5c8afe929ee38155db94de6b084ec32a645 (patch) | |
| tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /test/CodeGenCXX | |
| parent | 5044f5c816adfd5cba17f1adee1a10127296d0bf (diff) | |
Update clang to r96341.
Notes
Notes:
svn path=/vendor/clang/dist/; revision=203955
Diffstat (limited to 'test/CodeGenCXX')
42 files changed, 1213 insertions, 239 deletions
diff --git a/test/CodeGenCXX/PR4890-debug-info-dtor.cpp b/test/CodeGenCXX/PR4890-debug-info-dtor.cpp deleted file mode 100644 index bcaf1b96274e..000000000000 --- a/test/CodeGenCXX/PR4890-debug-info-dtor.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm-only -g %s -struct X { - ~X(); -}; - -X::~X() { } diff --git a/test/CodeGenCXX/alloca-align.cpp b/test/CodeGenCXX/alloca-align.cpp new file mode 100644 index 000000000000..de6b34d06072 --- /dev/null +++ b/test/CodeGenCXX/alloca-align.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// +// CHECK: alloca %struct.MemsetRange, align 16 + +struct MemsetRange { + int Start, End; + unsigned Alignment; + int TheStores __attribute__((aligned(16))); +}; +void foobar() { + (void) MemsetRange(); +} diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp index 7689c941e103..695f8f59defc 100644 --- a/test/CodeGenCXX/anonymous-namespaces.cpp +++ b/test/CodeGenCXX/anonymous-namespaces.cpp @@ -1,9 +1,25 @@ // RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s + +int f(); + namespace { + // CHECK: @_ZN12_GLOBAL__N_11bE = internal global i32 0 + // CHECK: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 + // CHECK: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 // CHECK: @_ZN12_GLOBAL__N_11aE = internal global i32 0 int a = 0; + int b = f(); + + static int c = f(); + + class D { + static int d; + }; + + int D::d = f(); + // CHECK: define internal i32 @_ZN12_GLOBAL__N_13fooEv() int foo() { return 32; diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp index 1b214b77bee7..4c781c62b29f 100644 --- a/test/CodeGenCXX/attr.cpp +++ b/test/CodeGenCXX/attr.cpp @@ -1,39 +1,20 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -O0 -S %s -o %t.s -// RUN: FileCheck --input-file=%t.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s +// CHECK: define i32 @_Z3foov() nounwind align 1024 int foo() __attribute__((aligned(1024))); int foo() { } -// CHECK:.align 10, 0x90 -// CHECK:.globl __Z3foov -// CHECK:__Z3foov: - - class C { virtual void bar1() __attribute__((aligned(1))); virtual void bar2() __attribute__((aligned(2))); virtual void bar3() __attribute__((aligned(1024))); } c; -// CHECK:.align 1, 0x90 -// CHECK-NEXT:.globl __ZN1CC1Ev - +// CHECK: define void @_ZN1C4bar1Ev(%class.C* %this) nounwind align 2 void C::bar1() { } -// CHECK:.align 1, 0x90 -// CHECK-NEXT:.globl __ZN1C4bar1Ev -// CHECK-NEXT:__ZN1C4bar1Ev: - - +// CHECK: define void @_ZN1C4bar2Ev(%class.C* %this) nounwind align 2 void C::bar2() { } -// CHECK:.align 1, 0x90 -// CHECK-NEXT:.globl __ZN1C4bar2Ev -// CHECK-NEXT:__ZN1C4bar2Ev: - - +// CHECK: define void @_ZN1C4bar3Ev(%class.C* %this) nounwind align 1024 void C::bar3() { } - -// CHECK:.align 10, 0x90 -// CHECK-NEXT:.globl __ZN1C4bar3Ev -// CHECK-NEXT:__ZN1C4bar3Ev: diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp index a1b7a09aa347..e435408aa840 100644 --- a/test/CodeGenCXX/condition.cpp +++ b/test/CodeGenCXX/condition.cpp @@ -64,7 +64,7 @@ void switch_destruct(int z) { z = 19; break; } - // CHECK: {{sw.epilog:|:4}} + // CHECK: {{sw.epilog:|:5}} // CHECK: call void @_ZN16ConvertibleToIntD1Ev // CHECK: store i32 20 z = 20; @@ -74,18 +74,18 @@ int foo(); void while_destruct(int z) { // CHECK: define void @_Z14while_destructi - // CHECK: {{while.cond:|:1}} + // CHECK: {{while.cond:|:2}} while (X x = X()) { // CHECK: call void @_ZN1XC1Ev - // CHECK: {{while.body:|:3}} + // CHECK: {{while.body:|:4}} // CHECK: store i32 21 z = 21; - // CHECK: {{while.cleanup:|:4}} + // CHECK: {{while.cleanup:|:5}} // CHECK: call void @_ZN1XD1Ev } - // CHECK: {{while.end|:6}} + // CHECK: {{while.end|:7}} // CHECK: store i32 22 z = 22; } @@ -94,16 +94,16 @@ void for_destruct(int z) { // CHECK: define void @_Z12for_destruct // CHECK: call void @_ZN1YC1Ev for(Y y = Y(); X x = X(); ++z) - // CHECK: {{for.cond:|:1}} + // CHECK: {{for.cond:|:2}} // CHECK: call void @_ZN1XC1Ev - // CHECK: {{for.body:|:3}} + // CHECK: {{for.body:|:4}} // CHECK: store i32 23 z = 23; - // CHECK: {{for.inc:|:4}} - // CHECK: br label %{{for.cond.cleanup|7}} - // CHECK: {{for.cond.cleanup:|:7}} + // CHECK: {{for.inc:|:5}} + // CHECK: br label %{{for.cond.cleanup|8}} + // CHECK: {{for.cond.cleanup:|:8}} // CHECK: call void @_ZN1XD1Ev - // CHECK: {{for.end:|:9}} + // CHECK: {{for.end:|:10}} // CHECK: call void @_ZN1YD1Ev // CHECK: store i32 24 z = 24; diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp index 0eac10b43cfd..d5382872f9d9 100644 --- a/test/CodeGenCXX/conditional-temporaries.cpp +++ b/test/CodeGenCXX/conditional-temporaries.cpp @@ -1,28 +1,55 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O3 | FileCheck %s -struct I { +namespace { + +static int ctorcalls; +static int dtorcalls; + +struct A { + A() : i(0) { ctorcalls++; } + ~A() { dtorcalls++; } int i; - I(); - ~I(); + + friend const A& operator<<(const A& a, int n) { + return a; + } }; -void g(int); +void g(int) { } +void g(const A&) { } -volatile int i; +void f1(bool b) { + g(b ? A().i : 0); + g(b || A().i); + g(b && A().i); + g(b ? A() << 1 : A() << 2); +} -void f1() { - // CHECK: call void @_ZN1IC1Ev - g(i ? I().i : 0); - // CHECK: call void @_Z1gi - // CHECK: call void @_ZN1ID1Ev +struct Checker { + Checker() { + f1(true); + f1(false); + } +}; - // CHECK: call void @_ZN1IC1Ev - g(i || I().i); - // CHECK: call void @_Z1gi - // CHECK: call void @_ZN1ID1Ev +Checker c; + +} + +// CHECK: define i32 @_Z12getCtorCallsv() +int getCtorCalls() { + // CHECK: ret i32 5 + return ctorcalls; +} + +// CHECK: define i32 @_Z12getDtorCallsv() +int getDtorCalls() { + // CHECK: ret i32 5 + return dtorcalls; +} - // CHECK: call void @_ZN1IC1Ev - g(i && I().i); - // CHECK: call void @_Z1gi - // CHECK: call void @_ZN1ID1Ev +// CHECK: define zeroext i1 @_Z7successv() +bool success() { + // CHECK: ret i1 true + return ctorcalls == dtorcalls; } diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp index f88bc808a7c6..d0a055b49495 100644 --- a/test/CodeGenCXX/const-global-linkage.cpp +++ b/test/CodeGenCXX/const-global-linkage.cpp @@ -3,11 +3,11 @@ const int x = 10; const int y = 20; // CHECK-NOT: @x -// CHECK: @y = internal constant i32 20 +// CHECK: @_ZL1y = internal constant i32 20 const int& b() { return y; } const char z1[] = "asdf"; const char z2[] = "zxcv"; // CHECK-NOT: @z1 -// CHECK: @z2 = internal constant +// CHECK: @_ZL2z2 = internal constant const char* b2() { return z2; } diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index 874b5f64e2ba..9cfce7ace86b 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -2,11 +2,11 @@ // CHECK: @a = global i32 10 int a = 10; -// CHECK: @ar = global i32* @a +// CHECK: @ar = constant i32* @a int &ar = a; void f(); -// CHECK: @fr = global void ()* @_Z1fv +// CHECK: @fr = constant void ()* @_Z1fv void (&fr)() = f; struct S { int& a; }; diff --git a/test/CodeGenCXX/conversion-function.cpp b/test/CodeGenCXX/conversion-function.cpp index fccb6f094e07..e2f8f7e17b93 100644 --- a/test/CodeGenCXX/conversion-function.cpp +++ b/test/CodeGenCXX/conversion-function.cpp @@ -2,7 +2,7 @@ // RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s // RUN: %clang_cc1 -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s // RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s - +// XFAIL: * extern "C" int printf(...); struct S { operator int(); diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index cb6e830a49e0..6bb9533a477e 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -g +// RUN: %clang_cc1 -emit-llvm-only -g %s template<typename T> struct Identity { typedef T Type; }; @@ -24,3 +24,29 @@ namespace EmptyNameCrash { typedef struct { A x; } B; B x; } + +// PR4890 +namespace PR4890 { + struct X { + ~X(); + }; + + X::~X() { } +} + +namespace VirtualDtor { + struct Y { + virtual ~Y(); + }; + + Y::~Y() { } +} + +namespace VirtualBase { + struct A { }; + struct B : virtual A { }; + + void f() { + B b; + } +} diff --git a/test/CodeGenCXX/default-destructor-synthesis.cpp b/test/CodeGenCXX/default-destructor-synthesis.cpp index 71167a204fbb..fac5cc01f6b7 100644 --- a/test/CodeGenCXX/default-destructor-synthesis.cpp +++ b/test/CodeGenCXX/default-destructor-synthesis.cpp @@ -1,58 +1,36 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++0x -O0 -S %s -o %t-32.s -// RUN: FileCheck -check-prefix LP32 -input-file=%t-32.s %s - -extern "C" int printf(...); - -int count = 1; +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O2 -o - | FileCheck %s +static int count = 0; struct S { - S() : iS(count++), fS(1.23) {}; - ~S(){printf("S::~S(%d, %f)\n", iS, fS); }; - int iS; - float fS; + S() { count++; } + ~S() { count--; } }; -struct Q { - Q() : iQ(count++), dQ(2.34) {}; - ~Q(){printf("Q::~Q(%d, %f)\n", iQ, dQ); }; - int iQ; - double dQ; +struct P { + P() { count++; } + ~P() { count--; } }; -struct P { - P() : fP(3.45) , iP(count++) {}; - ~P(){printf("P::~P(%d, %f)\n", iP, fP); }; - float fP; - int iP; +struct Q { + Q() { count++; } + ~Q() { count--; } }; -struct M : Q, P { +struct M : Q, P { S s; - Q q; - - P p; - - P p_arr[3]; - - Q q_arr[2][3]; - + P p; + P p_arr[3]; + Q q_arr[2][3]; }; - -M gm; - -int main() {M m1;} - -// CHECK-LP64: .globl __ZN1MD1Ev -// CHECK-LP64-NEXT: .weak_definition __ZN1MD1Ev -// CHECK-LP64-NEXT: __ZN1MD1Ev: -// CHECK-LP64: callq __ZN1MC1Ev -// CHECK-LP64: callq __ZN1MD1Ev - -// CHECK-LP32: .globl __ZN1MD1Ev -// CHECK-LP32-NEXT: .weak_definition __ZN1MD1Ev -// CHECK-LP32-NEXT:__ZN1MD1Ev: -// CHECK-LP32: call L__ZN1MC1Ev -// CHECK-LP32: call L__ZN1MD1Ev + +// CHECK: define i32 @_Z1fv() nounwind +int f() { + { + count = 1; + M a; + } + + // CHECK: ret i32 1 + return count; +} diff --git a/test/CodeGenCXX/deferred-global-init.cpp b/test/CodeGenCXX/deferred-global-init.cpp index 570147905548..802042dd8b90 100644 --- a/test/CodeGenCXX/deferred-global-init.cpp +++ b/test/CodeGenCXX/deferred-global-init.cpp @@ -5,7 +5,7 @@ extern void* foo; static void* const a = foo; void* bar() { return a; } -// CHECK: @a = internal global i8* null +// CHECK: @_ZL1a = internal global i8* null // CHECK: define internal void @__cxx_global_var_init // CHECK: load i8** @foo diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp index 45728b7c0122..e44fdc5ed2de 100644 --- a/test/CodeGenCXX/derived-to-base.cpp +++ b/test/CodeGenCXX/derived-to-base.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s struct A { void f(); @@ -14,3 +14,23 @@ void f() { b.f(); } + +// CHECK: define %struct.B* @_Z1fP1A(%struct.A* %a) nounwind +B *f(A *a) { + // CHECK-NOT: br label + // CHECK: ret %struct.B* + return static_cast<B*>(a); +} + +// PR5965 +namespace PR5965 { + +// CHECK: define %struct.A* @_ZN6PR59651fEP1B(%struct.B* %b) nounwind +A *f(B* b) { + // CHECK-NOT: br label + // CHECK: ret %struct.A* + return b; +} + +} + diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp index 054b972bb158..127cdd89683d 100644 --- a/test/CodeGenCXX/dyncast.cpp +++ b/test/CodeGenCXX/dyncast.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -I%S -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll // RUN: FileCheck -check-prefix LL --input-file=%t.ll %s +// XFAIL: win32 #include <typeinfo> @@ -69,14 +70,7 @@ void test1() { // CHECK-LL-NEXT: [[ep:%.*]] = alloca %class.test1_E*, align 8 // CHECK-LL-NEXT: [[vp:%.*]] = alloca i8*, align 8 // CHECK-LL-NEXT: [[cvp:%.*]] = alloca i8*, align 8 -// CHECK-LL-NEXT: br i1 false, label %[[castnull:.*]], label %[[castnotnull:.*]] -// CHECK-LL: [[castnotnull]] -// CHECK-LL-NEXT: br label %[[castend:.*]] -// CHECK-LL: [[castnull]] -// CHECK-LL-NEXT: br label %[[castend]] -// CHECK-LL: [[castend]] -// CHECK-LL-NEXT: [[v0:%.*]] = phi %class.test1_A* [ bitcast (%class.test1_D* @test1_d to %class.test1_A*), %[[castnotnull]] ], [ null, %[[castnull]] ] -// CHECK-LL-NEXT: store %class.test1_A* [[v0]], %class.test1_A** [[bp]] +// CHECK-LL-NEXT: store %class.test1_A* bitcast (%class.test1_D* @test1_d to %class.test1_A*), %class.test1_A** [[bp]] // CHECK-LL-NEXT: br i1 false, label %[[castnull2:.*]], label %[[castnotnull1:.*]] // CHECK-LL: [[castnotnull1]] // CHECK-LL-NEXT: [[vtable:%.*]] = load i8** bitcast (%class.test1_D* @test1_d to i8**) @@ -333,23 +327,10 @@ void test1() { // CHECK-LL-NEXT: call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str1, i32 0, i32 0), i32 12) // CHECK-LL-NEXT: br label %[[ifend113]] // CHECK-LL: [[ifend113]] -// CHECK-LL-NEXT: br i1 false, label %[[castnull116:.*]], label %[[castnotnull115:.*]] -// CHECK-LL: [[castnotnull115]] -// CHECK-LL-NEXT: br label %[[castend117:.*]] -// CHECK-LL: [[castnull116]] -// CHECK-LL-NEXT: br label %[[castend117]] -// CHECK-LL: [[castend117]] -// CHECK-LL-NEXT: [[v62:%.*]] = phi %class.test1_E* [ bitcast (%class.test1_F* @test1_f to %class.test1_E*), %[[castnotnull115]] ], [ null, %[[castnull116]] ] -// CHECK-LL-NEXT: store %class.test1_E* [[v62]], %class.test1_E** [[ep]] +// CHECK-LL-NEXT: store %class.test1_E* bitcast (%class.test1_F* @test1_f to %class.test1_E*), %class.test1_E** [[ep]] // CHECK-LL-NEXT: [[tmp118:%.*]] = load %class.test1_E** [[ep]] -// CHECK-LL-NEXT: br i1 false, label %[[castnull120:.*]], label %[[castnotnull119:.*]] -// CHECK-LL: [[castnotnull119]] -// CHECK-LL-NEXT: br label %[[castend121:.*]] -// CHECK-LL: [[castnull120]] -// CHECK-LL-NEXT: br label %[[castend121]] -// CHECK-LL: [[castend121]] -// CHECK-LL-NEXT: [[v63:%.*]] = phi %class.test1_E* [ bitcast (%class.test1_F* @test1_f to %class.test1_E*), %[[castnotnull119]] ], [ null, %[[castnull120]] ] -// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], [[v63]] +// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], bitcast (%class.test1_F* @test1_f to %class.test1_E*) ; <i1> [#uses=1] + // CHECK-LL-NEXT: br i1 [[cmp122]], label %[[ifthen123:.*]], label %[[ifelse125:.*]] // CHECK-LL: [[ifthen123]] // CHECK-LL-NEXT: call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0), i32 13) diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp index 427a45aebb1e..ca5cd7372cad 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -10,4 +10,7 @@ extern int b; // RUN: grep "@_ZN3foo1cE = global i32" %t | count 1 int c = 5; +// RUN: not grep "@_ZN3foo1dE" %t +extern "C" struct d; + } diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index b375aef4c8e0..b60e056d708f 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -7,6 +7,12 @@ struct A { struct B { B(); ~B(); }; +struct C { void *field; }; + +struct D { ~D(); }; + +// CHECK: @c = global %struct.C zeroinitializer, align 8 + // CHECK: call void @_ZN1AC1Ev(%struct.A* @a) // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) A a; @@ -14,3 +20,12 @@ A a; // CHECK: call void @_ZN1BC1Ev(%struct.A* @b) // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1BD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @b, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) B b; + +// PR6205: this should not require a global initializer +// CHECK-NOT: call void @_ZN1CC1Ev(%struct.C* @c) +C c; + +// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) +D d; + +// CHECK: define internal void @__cxx_global_initialization() { diff --git a/test/CodeGenCXX/global-llvm-constant.cpp b/test/CodeGenCXX/global-llvm-constant.cpp index e799231ab744..ef1dcf0c59bf 100644 --- a/test/CodeGenCXX/global-llvm-constant.cpp +++ b/test/CodeGenCXX/global-llvm-constant.cpp @@ -7,4 +7,4 @@ struct A { const A x; -// CHECK: @x = internal global +// CHECK: @_ZL1x = internal global diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp new file mode 100644 index 000000000000..1ae0f08f86ee --- /dev/null +++ b/test/CodeGenCXX/internal-linkage.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +struct Global { }; +template<typename T> struct X { }; + + +namespace { + struct Anon { }; + + // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global + Global anon0; +} + +// CHECK: @anon1 = internal global +Anon anon1; + +// CHECK: @anon2 = internal global +X<Anon> anon2; + diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp new file mode 100644 index 000000000000..cdad39852c9f --- /dev/null +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s + +template < bool condition, typename T = void > +struct enable_if { typedef T type; }; + +template< typename T > +struct enable_if< false, T > {}; + +// PR5876 +namespace Casts { + template< unsigned O > + void implicit(typename enable_if< O <= 4 >::type* = 0) { + } + + template< unsigned O > + void cstyle(typename enable_if< O <= (unsigned)4 >::type* = 0) { + } + + template< unsigned O > + void functional(typename enable_if< O <= unsigned(4) >::type* = 0) { + } + + template< unsigned O > + void static_(typename enable_if< O <= static_cast<unsigned>(4) >::type* = 0) { + } + + // FIXME: Test const_cast, reinterpret_cast, dynamic_cast, which are + // a bit harder to use in template arguments. + template <unsigned N> struct T {}; + + template <int N> T<N> f() { return T<N>(); } + + // CHECK: define void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE + template void implicit<4>(void*); + // CHECK: define void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE + template void cstyle<4>(void*); + // CHECK: define void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE + template void functional<4>(void*); + // CHECK: define void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE + template void static_<4>(void*); + + // CHECK: define i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv + template T<6> f<6>(); +} diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 5947587eec32..07183782e75e 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks | FileCheck %s - struct X { }; struct Y { }; @@ -9,6 +8,9 @@ struct Y { }; // CHECK: @_ZZN1N1gEvE1a = internal global // CHECK: @_ZGVZN1N1gEvE1a = internal global +//CHECK: @pr5966_i = external global +//CHECK: @_ZL8pr5966_i = internal global + // CHECK: define zeroext i1 @_ZplRK1YRA100_P1X bool operator+(const Y&, X* (&xs)[100]) { return false; } @@ -310,7 +312,67 @@ template class Alloc<char>; // CHECK: define void @_Z1fU13block_pointerFiiiE void f(int (^)(int, int)) { } -// PR5869 -// CHECK: define internal void @_ZL2f2v -static void f2() {} -void f3() { f2(); } +void pr5966_foo() { + extern int pr5966_i; + pr5966_i = 0; +} + +static int pr5966_i; + +void pr5966_bar() { + pr5966_i = 0; +} + +namespace test0 { + int ovl(int x); + char ovl(double x); + + template <class T> void f(T, char (&buffer)[sizeof(ovl(T()))]) {} + + void test0() { + char buffer[1]; + f(0.0, buffer); + } + // CHECK: define void @_ZN5test05test0Ev() + // CHECK: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c( + + void test1() { + char buffer[sizeof(int)]; + f(1, buffer); + } + // CHECK: define void @_ZN5test05test1Ev() + // CHECK: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c( + + template <class T> void g(char (&buffer)[sizeof(T() + 5.0f)]) {} + void test2() { + char buffer[sizeof(float)]; + g<float>(buffer); + } + // CHECK: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40A00000E_c( + + template <class T> void h(char (&buffer)[sizeof(T() + 5.0)]) {} + void test3() { + char buffer[sizeof(double)]; + h<float>(buffer); + } + // CHECK: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c( + + template <class T> void j(char (&buffer)[sizeof(T().buffer)]) {} + struct A { double buffer[128]; }; + void test4() { + char buffer[1024]; + j<A>(buffer); + } + // CHECK: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszmecvT__E6buffer_c( +} + +namespace test1 { + template<typename T> struct X { }; + template<template<class> class Y, typename T> void f(Y<T>) { } + // CHECK: define void @_ZN5test11fINS_1XEiEEvT_IT0_E + template void f(X<int>); +} + +// CHECK: define internal void @_Z27functionWithInternalLinkagev() +static void functionWithInternalLinkage() { } +void g() { functionWithInternalLinkage(); } diff --git a/test/CodeGenCXX/member-function-pointer-calls.cpp b/test/CodeGenCXX/member-function-pointer-calls.cpp new file mode 100644 index 000000000000..e1f2eb78d414 --- /dev/null +++ b/test/CodeGenCXX/member-function-pointer-calls.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s +struct A { + virtual int vf1() { return 1; } + virtual int vf2() { return 2; } +}; + +int f(A* a, int (A::*fp)()) { + return (a->*fp)(); +} + +// CHECK: define i32 @_Z2g1v() +int g1() { + A a; + + // CHECK: call i32 @_ZN1A3vf1Ev + // CHECK-NEXT: ret i32 + return f(&a, &A::vf1); +} + +int g2() { + A a; + + // CHECK: call i32 @_ZN1A3vf2Ev + // CHECK-NEXT: ret i32 + return f(&a, &A::vf2); +} diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index e1353a72b396..f7c445b1cb10 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s -struct A { int a; void f(); virtual void vf(); }; +struct A { int a; void f(); virtual void vf1(); virtual void vf2(); }; struct B { int b; virtual void g(); }; struct C : B, A { }; @@ -9,17 +9,20 @@ void (A::*volatile vpa)(); void (B::*pb)(); void (C::*pc)(); -// CHECK: @pa2 = global %0 { i64 ptrtoint (void ()* @_ZN1A1fEv to i64), i64 0 }, align 8 +// CHECK: @pa2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }, align 8 void (A::*pa2)() = &A::f; // CHECK: @pa3 = global %0 { i64 1, i64 0 }, align 8 -void (A::*pa3)() = &A::vf; +void (A::*pa3)() = &A::vf1; -// CHECK: @pc2 = global %0 { i64 ptrtoint (void ()* @_ZN1A1fEv to i64), i64 16 }, align 8 +// CHECK: @pa4 = global %0 { i64 9, i64 0 }, align 8 +void (A::*pa4)() = &A::vf2; + +// CHECK: @pc2 = global %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 16 }, align 8 void (C::*pc2)() = &C::f; // CHECK: @pc3 = global %0 { i64 1, i64 0 }, align 8 -void (A::*pc3)() = &A::vf; +void (A::*pc3)() = &A::vf1; void f() { // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0) @@ -43,7 +46,7 @@ void f() { void f2() { // CHECK: [[pa2ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 0 - // CHECK: store i64 ptrtoint (void ()* @_ZN1A1fEv to i64), i64* [[pa2ptr]] + // CHECK: store i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64* [[pa2ptr]] // CHECK: [[pa2adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 1 // CHECK: store i64 0, i64* [[pa2adj]] void (A::*pa2)() = &A::f; @@ -52,7 +55,13 @@ void f2() { // CHECK: store i64 1, i64* [[pa3ptr]] // CHECK: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1 // CHECK: store i64 0, i64* [[pa3adj]] - void (A::*pa3)() = &A::vf; + void (A::*pa3)() = &A::vf1; + + // CHECK: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0 + // CHECK: store i64 9, i64* [[pa4ptr]] + // CHECK: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1 + // CHECK: store i64 0, i64* [[pa4adj]] + void (A::*pa4)() = &A::vf2; } void f3(A *a, A &ar) { @@ -150,3 +159,17 @@ namespace MemberPointerImpCast { (obj->*method)(); } } + +// PR6258 +namespace PR6258 { + + struct A { + void f(bool); + }; + + void (A::*pf)(bool) = &A::f; + + void f() { + void (A::*pf)(bool) = &A::f; + } +} diff --git a/test/CodeGenCXX/member-initializers.cpp b/test/CodeGenCXX/member-initializers.cpp new file mode 100644 index 000000000000..81dcee7e407a --- /dev/null +++ b/test/CodeGenCXX/member-initializers.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -O3 | FileCheck %s + +struct A { + virtual int f() { return 1; } +}; + +struct B : A { + B() : i(f()) { } + + virtual int f() { return 2; } + + int i; +}; + +// CHECK: define i32 @_Z1fv() nounwind +int f() { + B b; + + // CHECK: call i32 @_ZN1B1fEv + return b.i; +} + +// Test that we don't try to fold the default value of j when initializing i. +// CHECK: define i32 @_Z9test_foldv() nounwind +int test_fold() { + struct A { + A(const int j = 1) : i(j) { } + int i; + }; + + // CHECK: ret i32 2 + return A(2).i; +} + diff --git a/test/CodeGenCXX/member-pointer-cast.cpp b/test/CodeGenCXX/member-pointer-cast.cpp deleted file mode 100644 index 4937b037de53..000000000000 --- a/test/CodeGenCXX/member-pointer-cast.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s - -struct A { int a; }; -struct B { int b; }; -struct C : B, A { }; - -int A::*pa; -int C::*pc; - -void f() { - // CHECK: store i64 -1, i64* @pa - pa = 0; - - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 4 - // CHECK: store i64 [[ADJ]], i64* @pc - pc = pa; - - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 4 - // CHECK: store i64 [[ADJ]], i64* @pa - pa = static_cast<int A::*>(pc); -} diff --git a/test/CodeGenCXX/member-pointers-zero-init.cpp b/test/CodeGenCXX/member-pointers-zero-init.cpp deleted file mode 100644 index 18a2ead1ede5..000000000000 --- a/test/CodeGenCXX/member-pointers-zero-init.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 - -struct A { - int i; -}; - -// RUN: grep "@a = global i64 -1" %t -int A::* a; - -// RUN: grep "@aa = global \[2 x i64\] \[i64 -1, i64 -1\]" %t -int A::* aa[2]; - -// RUN: grep "@aaa = global \[2 x \[2 x i64\]\] \[\[2 x i64\] \[i64 -1, i64 -1\], \[2 x i64\] \[i64 -1, i64 -1\]\]" %t -int A::* aaa[2][2]; - -// RUN: grep "@b = global i64 -1" %t -int A::* b = 0; - -void f() { - // RUN: grep "%.* = icmp ne i64 %.*, -1" %t | count 2 - if (a) { } - if (a != 0) { } - - // RUN: grep "%.* = icmp ne i64 -1, %.*" %t | count 1 - if (0 != a) { } - - // RUN: grep "%.* = icmp eq i64 %.*, -1" %t | count 1 - if (a == 0) { } - - // RUN: grep "%.* = icmp eq i64 -1, %.*" %t | count 1 - if (0 == a) { } - -} - diff --git a/test/CodeGenCXX/no-exceptions.cpp b/test/CodeGenCXX/no-exceptions.cpp new file mode 100644 index 000000000000..da672c43f8d4 --- /dev/null +++ b/test/CodeGenCXX/no-exceptions.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +void g(); + +// CHECK: define void @_Z1fv() nounwind +void f() throw (int) { + + // CHECK-NOT: invoke void @_Z1gv + g(); + // CHECK: call void @_Z1gv() + // CHECK: ret void +} diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp new file mode 100644 index 000000000000..d96eb03b8d82 --- /dev/null +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s + +struct A { int a; int b; }; +struct B { int b; }; +struct C : B, A { }; + +// Zero init. +namespace ZeroInit { + // CHECK: @_ZN8ZeroInit1aE = global i64 -1 + int A::* a; + + // CHECK: @_ZN8ZeroInit2aaE = global [2 x i64] [i64 -1, i64 -1] + int A::* aa[2]; + + // CHECK: @_ZN8ZeroInit3aaaE = global [2 x [2 x i64]] {{\[}}[2 x i64] [i64 -1, i64 -1], [2 x i64] [i64 -1, i64 -1]] + int A::* aaa[2][2]; + + // CHECK: @_ZN8ZeroInit1bE = global i64 -1, + int A::* b = 0; + + // CHECK: @_ZN8ZeroInit2saE = global %struct.anon { i64 -1 } + struct { + int A::*a; + } sa; + + // CHECK: @_ZN8ZeroInit3ssaE = + // CHECK: [2 x i64] [i64 -1, i64 -1] + struct { + int A::*aa[2]; + } ssa[2]; + + // CHECK: @_ZN8ZeroInit2ssE = global %1 { %struct.anon { i64 -1 } } + struct { + struct { + int A::*pa; + } s; + } ss; +} + +// PR5674 +namespace PR5674 { + // CHECK: @_ZN6PR56742pbE = global i64 4 + int A::*pb = &A::b; +} + +// Casts. +namespace Casts { + +int A::*pa; +int C::*pc; + +void f() { + // CHECK: store i64 -1, i64* @_ZN5Casts2paE + pa = 0; + + // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 4 + // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2pcE + pc = pa; + + // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 4 + // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2paE + pa = static_cast<int A::*>(pc); +} + +} + +// Comparisons +namespace Comparisons { + void f() { + int A::*a; + + // CHECK: icmp ne i64 {{.*}}, -1 + if (a) { } + + // CHECK: icmp ne i64 {{.*}}, -1 + if (a != 0) { } + + // CHECK: icmp ne i64 -1, {{.*}} + if (0 != a) { } + + // CHECK: icmp eq i64 {{.*}}, -1 + if (a == 0) { } + + // CHECK: icmp eq i64 -1, {{.*}} + if (0 == a) { } + } +} diff --git a/test/CodeGenCXX/reference-init.cpp b/test/CodeGenCXX/reference-init.cpp index 6c2c6a301681..9469c84eb5d0 100644 --- a/test/CodeGenCXX/reference-init.cpp +++ b/test/CodeGenCXX/reference-init.cpp @@ -14,3 +14,11 @@ namespace PR5911 { int iarr[] = { 1 }; int test() { return f(iarr); } } + +// radar 7574896 +struct Foo { int foo; }; +Foo& ignoreSetMutex = *(new Foo); + +// Binding to a bit-field that requires a temporary. +struct { int bitfield : 3; } s = { 3 }; +const int &s2 = s.bitfield; diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 6bec8bd8c384..39b5909fb9a4 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -38,6 +38,8 @@ void test_bool() { bool_reference_return() = true; a = bool_reference_return(); + + struct { const bool& b; } b = { true }; } void test_scalar() { @@ -54,6 +56,8 @@ void test_scalar() { int_reference_return() = 10; a = int_reference_return(); + + struct { const int& a; } agg = { 10 }; } void test_complex() { @@ -64,6 +68,8 @@ void test_complex() { complex_int_reference_return() = 10i; a = complex_int_reference_return(); + + struct { const _Complex int &a; } agg = { 10i }; } void test_aggregate() { @@ -74,6 +80,8 @@ void test_aggregate() { aggregate_reference_return().a = 10; c = aggregate_reference_return(); + + struct { const C& a; } agg = { C() }; } int& reference_return() { diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp index 53a1d5e4c450..b3a2af2aafe3 100644 --- a/test/CodeGenCXX/static-data-member.cpp +++ b/test/CodeGenCXX/static-data-member.cpp @@ -1,4 +1,14 @@ // RUN: %clang_cc1 -emit-llvm -o - %s + +// CHECK: @_ZN1A1aE = constant i32 10 + +// PR5564. +struct A { + static const int a = 10; +}; + +const int A::a; + struct S { static int i; }; diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index cbd90e789406..a67d137d6a1d 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -1,4 +1,10 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZZ1hvE1i = internal global i32 0, align 4 + +// CHECK: @_ZZ2h2vE1i = weak global i32 0 +// CHECK: @_ZGVZ2h2vE1i = weak global i64 0 + struct A { A(); ~A(); @@ -15,3 +21,16 @@ void g() { // CHECK: call void @_ZN1AC1Ev( static A& a = *new A; } + +int a(); +void h() { + static const int i = a(); +} + +inline void h2() { + static int i = a(); +} + +void h3() { + h2(); +} diff --git a/test/CodeGenCXX/temp-order.cpp b/test/CodeGenCXX/temp-order.cpp index 05a9aed2defa..341cd0ca134a 100644 --- a/test/CodeGenCXX/temp-order.cpp +++ b/test/CodeGenCXX/temp-order.cpp @@ -129,10 +129,30 @@ static unsigned f6() { return tt.Product; } +// 5, 2 +static unsigned f7() { + TempTracker tt; + { + (void)((A(tt, 2, false) && A(tt, 3, false)) || A(tt, 5, false)); + } + return tt.Product; +} + +// 5, 2 +static unsigned f8() { + TempTracker tt; + + { + (void)((A(tt, 2) || A(tt, 3)) && A(tt, 5)); + } + return tt.Product; +} + extern "C" void error(); extern "C" void print(const char *Name, unsigned N); -#define ORDER3(a, b, c) (pow(a, 1) * pow(b, 2) * pow(c, 3)) +#define ORDER2(a, b) (pow(a, 1) * pow(b, 2)) +#define ORDER3(a, b, c) (ORDER2(a, b) * pow(c, 3)) #define ORDER4(a, b, c, d) (ORDER3(a, b, c) * pow(d, 4)) #define ORDER5(a, b, c, d, e) (ORDER4(a, b, c, d) * pow(e, 5)) #define ORDER6(a, b, c, d, e, f) (ORDER5(a, b, c, d, e) * pow(f, 6)) @@ -171,6 +191,16 @@ void test() { print("f6", f6()); if (f6() != ORDER6(3, 7, 11, 5, 13, 2)) error(); + +// CHECK: call void @print(i8* {{.*}}, i32 20) + print("f7", f7()); + if (f7() != ORDER2(5, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 20) + print("f8", f8()); + if (f8() != ORDER2(5, 2)) + error(); } diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 611781886b3e..3b624afd0ad1 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -249,3 +249,42 @@ namespace PR5867 { g2(17); } } + +// PR6199 +namespace PR6199 { + struct A { ~A(); }; + + struct B { operator A(); }; + + // CHECK: define void @_ZN6PR61992f2IiEENS_1AET_ + template<typename T> A f2(T) { + B b; + // CHECK: call void @_ZN6PR61991BcvNS_1AEEv + // CHECK-NEXT: ret void + return b; + } + + template A f2<int>(int); + +} + +namespace T12 { + +struct A { + A(); + ~A(); + int f(); +}; + +int& f(int); + +// CHECK: define void @_ZN3T121gEv +void g() { + // CHECK: call void @_ZN3T121AC1Ev + // CHECK-NEXT: call i32 @_ZN3T121A1fEv( + // CHECK-NEXT: call i32* @_ZN3T121fEi( + // CHECK-NEXT: call void @_ZN3T121AD1Ev( + int& i = f(A().f()); +} + +} diff --git a/test/CodeGenCXX/threadsafe-statics.cpp b/test/CodeGenCXX/threadsafe-statics.cpp new file mode 100644 index 000000000000..65ebc43c5d25 --- /dev/null +++ b/test/CodeGenCXX/threadsafe-statics.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=WITH-TSS %s +// RUN: %clang_cc1 -emit-llvm -o - %s -fno-threadsafe-statics | FileCheck -check-prefix=NO-TSS %s + +int f(); + +// WITH-TSS: define void @_Z1gv() nounwind +// WITH-TSS: call i32 @__cxa_guard_acquire +// WITH-TSS: call void @__cxa_guard_release +// WITH-TSS: ret void +void g() { + static int a = f(); +} + +// NO-TSS: define void @_Z1gv() nounwind +// NO-TSS-NOT: call i32 @__cxa_guard_acquire +// NO-TSS-NOT: call void @__cxa_guard_release +// NO-TSS: ret void diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp index 9449618f2f2c..1670e4450237 100644 --- a/test/CodeGenCXX/throw-expressions.cpp +++ b/test/CodeGenCXX/throw-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -verify %s +// RUN: %clang_cc1 -emit-llvm-only -verify %s -Wno-unreachable-code int val = 42; int& test1() { diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 22e11fd76e31..9d671c4e5f0e 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -384,11 +384,11 @@ struct test16_D : test16_NV1, virtual test16_B2 { // CHECK-LP64-NEXT: .quad __ZTcv0_n48_v0_n24_N8test16_D4foo1Ev // CHECK-LP64-NEXT: .quad __ZN9test16_B24foo2Ev // CHECK-LP64-NEXT: .quad __ZN9test16_B26foo_B2Ev -// CHECK-LP64-NEXT .quad 16 -// CHECK-LP64-NEXT .quad 16 +// CHECK-LP64-NEXT: .quad 16 +// CHECK-LP64-NEXT: .quad 16 // CHECK-LP64-NEXT: .quad 0 // CHECK-LP64-NEXT: .quad 0 -// CHECK-LP64: .quad -16 +// CHECK-LP64-NEXT: .quad -16 // CHECK-LP64-NEXT: .quad -32 // CHECK-LP64-NEXT: .quad 0 // CHECK-LP64-NEXT: .quad 0 @@ -402,8 +402,8 @@ struct test16_D : test16_NV1, virtual test16_B2 { // CHECK-LP64-NEXT: .quad __ZN8test16_B5foo_BEv // CHECK-LP64-NEXT: .quad -48 // CHECK-LP64-NEXT: .quad __ZTI8test16_D -// CHECK-LP64-NEXT .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev -// CHECK-LP64: .quad __ZN10test16_NV27foo_NV2Ev +// CHECK-LP64-NEXT: .quad __ZTcvn16_n40_v16_n32_N8test16_D4foo1Ev +// CHECK-LP64-NEXT: .quad __ZN10test16_NV27foo_NV2Ev // CHECK-LP64-NEXT: .quad __ZN10test16_NV28foo_NV2bEv @@ -696,32 +696,32 @@ void test12_foo() { // FIXME: This is the wrong thunk, but until these issues are fixed, better // than nothing. -// CHECK-LPLL64:define 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-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|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: %{{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}} diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 1eaef3fa3af4..200f21a5da72 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -15,3 +15,11 @@ struct B : virtual A { // CHECK: define void @_ZN1BC1Ev(%struct.B* %this) // CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) B::B() { } + +struct C : virtual A { + C(bool); +}; + +// CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext) +// CHECK: define void @_ZN1CC2Eb(%struct.B* %this, i8** %vtt, i1 zeroext) +C::C(bool) { } diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp index 0b3a684301eb..46e7b2d37f77 100644 --- a/test/CodeGenCXX/virtual-function-calls.cpp +++ b/test/CodeGenCXX/virtual-function-calls.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s // PR5021 +namespace PR5021 { + struct A { virtual void f(char); }; @@ -16,4 +18,21 @@ struct B : virtual A { void f(B * b) { b->f(); -}
\ No newline at end of file +} + +} + +namespace Test1 { + struct A { + virtual ~A(); + }; + + struct B : A { + virtual ~B(); + virtual void f(); + }; + + void f(B *b) { + b->f(); + } +} diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp new file mode 100644 index 000000000000..5edd27b8b279 --- /dev/null +++ b/test/CodeGenCXX/visibility.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +#define HIDDEN __attribute__((visibility("hidden"))) +#define PROTECTED __attribute__((visibility("protected"))) +#define DEFAULT __attribute__((visibility("default"))) + +// CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10 + +namespace Test1 { + // CHECK: define hidden void @_ZN5Test11fEv + void HIDDEN f() { } + +} + +namespace Test2 { + struct HIDDEN A { + void f(); + }; + + // A::f is a member function of a hidden class. + // CHECK: define hidden void @_ZN5Test21A1fEv + void A::f() { } +} + +namespace Test3 { + struct HIDDEN A { + struct B { + void f(); + }; + }; + + // B is a nested class where its parent class is hidden. + // CHECK: define hidden void @_ZN5Test31A1B1fEv + void A::B::f() { } +} + +namespace Test4 HIDDEN { + int VariableInHiddenNamespace = 10; + + // Test4::g is in a hidden namespace. + // CHECK: define hidden void @_ZN5Test41gEv + void g() { } + + struct DEFAULT A { + void f(); + }; + + // A has default visibility. + // CHECK: define void @_ZN5Test41A1fEv + void A::f() { } +} + +namespace Test5 { + + namespace NS HIDDEN { + // f is in NS which is hidden. + // CHECK: define hidden void @_ZN5Test52NS1fEv() + void f() { } + } + + namespace NS { + // g is in NS, but this NS decl is not hidden. + // CHECK: define void @_ZN5Test52NS1gEv + void g() { } + } +} diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp new file mode 100644 index 000000000000..8fbe486faa47 --- /dev/null +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -0,0 +1,367 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s + +// For now, just verify this doesn't crash. +namespace test0 { + struct Obj {}; + + struct Base { virtual const Obj *foo() = 0; }; + struct Derived : Base { virtual Obj *foo() { return new Obj(); } }; + + void test(Derived *D) { D->foo(); } +} + +namespace Test1 { +// CHECK: Vtable for 'Test1::A' (3 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test1::A RTTI +// CHECK-NEXT: -- (Test1::A, 0) vtable address -- +// CHECK-NEXT: 2 | void Test1::A::f() +struct A { + virtual void f(); +}; +void A::f() { } + +} + +namespace Test2 { + +// This is a smoke test of the vtable dumper. +// CHECK: Vtable for 'Test2::A' (9 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test2::A RTTI +// CHECK-NEXT: -- (Test2::A, 0) vtable address -- +// CHECK-NEXT: 2 | void Test2::A::f() +// CHECK-NEXT: 3 | void Test2::A::f() const +// CHECK-NEXT: 4 | Test2::A *Test2::A::g(int) +// CHECK-NEXT: 5 | Test2::A::~A() [complete] +// CHECK-NEXT: 6 | Test2::A::~A() [deleting] +// CHECK-NEXT: 7 | void Test2::A::h() +// CHECK-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) +struct A { + virtual void f(); + virtual void f() const; + + virtual A* g(int a); + virtual ~A(); + virtual void h(); + virtual A& operator=(const A&); +}; +void A::f() { } + +// Another simple vtable dumper test. + +// CHECK: Vtable for 'Test2::B' (6 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test2::B RTTI +// CHECK-NEXT: -- (Test2::B, 0) vtable address -- +// CHECK-NEXT: 2 | void Test2::B::f() +// CHECK-NEXT: 3 | void Test2::B::g() [pure] +// CHECK-NEXT: 4 | Test2::B::~B() [complete] [pure] +// CHECK-NEXT: 5 | Test2::B::~B() [deleting] [pure] +struct B { + virtual void f(); + virtual void g() = 0; + virtual ~B() = 0; +}; +void B::f() { } + +} + +namespace Test3 { + +// If a function in a derived class overrides a function in a primary base, +// then the function should not have an entry in the derived class (unless the return +// value requires adjusting). + +// CHECK: Vtable for 'Test3::A' (3 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test3::A RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-NEXT: 2 | void Test3::A::f() +struct A { + virtual void f(); +}; +void A::f() { } + +// CHECK: Vtable for 'Test3::B' (4 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test3::B RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-NEXT: -- (Test3::B, 0) vtable address -- +// CHECK-NEXT: 2 | void Test3::B::f() +// CHECK-NEXT: 3 | void Test3::B::g() +struct B : A { + virtual void f(); + virtual void g(); +}; +void B::f() { } + +// CHECK: Vtable for 'Test3::C' (5 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-NEXT: -- (Test3::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test3::A::f() +// CHECK-NEXT: 3 | void Test3::C::g() +// CHECK-NEXT: 4 | void Test3::C::h() +struct C : A { + virtual void g(); + virtual void h(); +}; +void C::g() { } + +// CHECK: Vtable for 'Test3::D' (5 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test3::D RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-NEXT: -- (Test3::B, 0) vtable address -- +// CHECK-NEXT: -- (Test3::D, 0) vtable address -- +// CHECK-NEXT: 2 | void Test3::D::f() +// CHECK-NEXT: 3 | void Test3::D::g() +// CHECK-NEXT: 4 | void Test3::D::h() +struct D : B { + virtual void f(); + virtual void g(); + virtual void h(); +}; + +void D::f() { } +} + +namespace Test4 { + +// Test non-virtual result adjustments. + +struct R1 { int r1; }; +struct R2 { int r2; }; +struct R3 : R1, R2 { int r3; }; + +struct A { + virtual R2 *f(); +}; + +// CHECK: Vtable for 'Test4::B' (4 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test4::B RTTI +// CHECK-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-NEXT: -- (Test4::B, 0) vtable address -- +// CHECK-NEXT: 2 | Test4::R3 *Test4::B::f() +// CHECK-NEXT: [return adjustment: 4 non-virtual] +// CHECK-NEXT: 3 | Test4::R3 *Test4::B::f() + +struct B : A { + virtual R3 *f(); +}; +R3 *B::f() { return 0; } + +// Test virtual result adjustments. +struct V1 { int v1; }; +struct V2 : virtual V1 { int v1; }; + +struct C { + virtual V1 *f(); +}; + +// CHECK: Vtable for 'Test4::D' (4 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test4::D RTTI +// CHECK-NEXT: -- (Test4::C, 0) vtable address -- +// CHECK-NEXT: -- (Test4::D, 0) vtable address -- +// CHECK-NEXT: 2 | Test4::V2 *Test4::D::f() +// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] +// CHECK-NEXT: 3 | Test4::V2 *Test4::D::f() +struct D : C { + virtual V2 *f(); +}; +V2 *D::f() { return 0; }; + +// Virtual result adjustments with an additional non-virtual adjustment. +struct V3 : virtual R3 { int r3; }; + +// CHECK: Vtable for 'Test4::E' (4 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test4::E RTTI +// CHECK-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-NEXT: -- (Test4::E, 0) vtable address -- +// CHECK-NEXT: 2 | Test4::V3 *Test4::E::f() +// CHECK-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset] +// CHECK-NEXT: 3 | Test4::V3 *Test4::E::f() + +struct E : A { + virtual V3 *f(); +}; +V3 *E::f() { return 0;} + +// Test that a pure virtual member doesn't get a thunk. + +// CHECK: Vtable for 'Test4::F' (5 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test4::F RTTI +// CHECK-NEXT: -- (Test4::A, 0) vtable address -- +// CHECK-NEXT: -- (Test4::F, 0) vtable address -- +// CHECK-NEXT: 2 | Test4::R3 *Test4::F::f() [pure] +// CHECK-NEXT: 3 | void Test4::F::g() +// CHECK-NEXT: 4 | Test4::R3 *Test4::F::f() [pure] +struct F : A { + virtual void g(); + virtual R3 *f() = 0; +}; +void F::g() { } + +} + +namespace Test5 { + +// Simple secondary vtables without 'this' pointer adjustments. +struct A { + virtual void f(); + virtual void g(); + int a; +}; + +struct B1 : A { + virtual void f(); + int b1; +}; + +struct B2 : A { + virtual void g(); + int b2; +}; + +// CHECK: Vtable for 'Test5::C' (9 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test5::C RTTI +// CHECK-NEXT: -- (Test5::A, 0) vtable address -- +// CHECK-NEXT: -- (Test5::B1, 0) vtable address -- +// CHECK-NEXT: -- (Test5::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test5::B1::f() +// CHECK-NEXT: 3 | void Test5::A::g() +// CHECK-NEXT: 4 | void Test5::C::h() +// CHECK-NEXT: 5 | offset_to_top (-16) +// CHECK-NEXT: 6 | Test5::C RTTI +// CHECK-NEXT: -- (Test5::A, 16) vtable address -- +// CHECK-NEXT: -- (Test5::B2, 16) vtable address -- +// CHECK-NEXT: 7 | void Test5::A::f() +// CHECK-NEXT: 8 | void Test5::B2::g() +struct C : B1, B2 { + virtual void h(); +}; +void C::h() { } +} + +namespace Test6 { + +// Simple non-virtual 'this' pointer adjustments. +struct A1 { + virtual void f(); + int a; +}; + +struct A2 { + virtual void f(); + int a; +}; + +// CHECK: Vtable for 'Test6::C' (6 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test6::C RTTI +// CHECK-NEXT: -- (Test6::A1, 0) vtable address -- +// CHECK-NEXT: -- (Test6::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test6::C::f() +// CHECK-NEXT: 3 | offset_to_top (-16) +// CHECK-NEXT: 4 | Test6::C RTTI +// CHECK-NEXT: -- (Test6::A2, 16) vtable address -- +// CHECK-NEXT: 5 | void Test6::C::f() +// CHECK-NEXT: [this adjustment: -16 non-virtual] +struct C : A1, A2 { + virtual void f(); +}; +void C::f() { } + +} + +namespace Test7 { + +// Test that the D::f overrider for A::f have different 'this' pointer +// adjustments in the two A base subobjects. + +struct A { + virtual void f(); + int a; +}; + +struct B1 : A { }; +struct B2 : A { }; + +struct C { virtual void c(); }; + +// CHECK: Vtable for 'Test7::D' (10 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test7::D RTTI +// CHECK-NEXT: -- (Test7::C, 0) vtable address -- +// CHECK-NEXT: -- (Test7::D, 0) vtable address -- +// CHECK-NEXT: 2 | void Test7::C::c() +// CHECK-NEXT: 3 | void Test7::D::f() +// CHECK-NEXT: 4 | offset_to_top (-8) +// CHECK-NEXT: 5 | Test7::D RTTI +// CHECK-NEXT: -- (Test7::A, 8) vtable address -- +// CHECK-NEXT: -- (Test7::B1, 8) vtable address -- +// CHECK-NEXT: 6 | void Test7::D::f() +// CHECK-NEXT: [this adjustment: -8 non-virtual] +// CHECK-NEXT: 7 | offset_to_top (-24) +// CHECK-NEXT: 8 | Test7::D RTTI +// CHECK-NEXT: -- (Test7::A, 24) vtable address -- +// CHECK-NEXT: -- (Test7::B2, 24) vtable address -- +// CHECK-NEXT: 9 | void Test7::D::f() +// CHECK-NEXT: [this adjustment: -24 non-virtual] +struct D : C, B1, B2 { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test8 { + +// Test that we don't try to layout vtables for classes that don't have +// virtual bases or virtual member functions. + +struct A { }; + +// CHECK: Vtable for 'Test8::B' (3 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test8::B RTTI +// CHECK-NEXT: -- (Test8::B, 0) vtable address -- +// CHECK-NEXT: 2 | void Test8::B::f() +struct B : A { + virtual void f(); +}; +void B::f() { } + +} + +namespace Test9 { + +// Simple test of vbase offsets. + +struct A1 { int a1; }; +struct A2 { int a2; }; + +// CHECK: Vtable for 'Test9::B' (5 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | vbase_offset (12) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test9::B RTTI +// CHECK-NEXT: -- (Test9::B, 0) vtable address -- +// CHECK-NEXT: 4 | void Test9::B::f() +struct B : virtual A1, virtual A2 { + int b; + + virtual void f(); +}; + + +void B::f() { } + +} diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp new file mode 100644 index 000000000000..92e011752f3f --- /dev/null +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct Field { + Field(); + ~Field(); +}; + +struct Base { + Base(); + ~Base(); +}; + +struct A : Base { + A(); + ~A(); + + virtual void f(); + + Field field; +}; + +// CHECK: define void @_ZN1AC1Ev( +// CHECK: call void @_ZN4BaseC2Ev( +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: call void @_ZN5FieldC1Ev( +// CHECK: ret void +A::A() { } + +// CHECK: define void @_ZN1AD1Ev( +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: call void @_ZN5FieldD1Ev( +// CHECK: call void @_ZN4BaseD2Ev( +// CHECK: ret void +A::~A() { } + +struct B : Base { + virtual void f(); + + Field field; +}; + +void f() { B b; } + +// CHECK: define linkonce_odr void @_ZN1BC1Ev( +// CHECK: call void @_ZN4BaseC2Ev( +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: call void @_ZN5FieldC1Ev +// CHECK: ret void + +// CHECK: define linkonce_odr void @_ZN1BD1Ev( +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: call void @_ZN5FieldD1Ev( +// CHECK: call void @_ZN4BaseD2Ev( +// CHECK: ret void diff --git a/test/CodeGenCXX/x86_32-arguments.cpp b/test/CodeGenCXX/x86_32-arguments.cpp new file mode 100644 index 000000000000..d13c0e4888fd --- /dev/null +++ b/test/CodeGenCXX/x86_32-arguments.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// Non-trivial dtors, should both be passed indirectly. +struct S { + ~S(); + int s; +}; + +// CHECK: define void @_Z1fv(%struct.S* noalias sret % +S f() { return S(); } +// CHECK: define void @_Z1f1S(%struct.S*) +void f(S) { } + +// Non-trivial dtors, should both be passed indirectly. +class C { + ~C(); + double c; +}; + +// CHECK: define void @_Z1gv(%class.C* noalias sret % +C g() { return C(); } + +// CHECK: define void @_Z1f1C(%class.C*) +void f(C) { } |
