diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-12-01 11:08:04 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-12-01 11:08:04 +0000 |
commit | 4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa (patch) | |
tree | 867cbbe32a66fd7d62dd9ce9df23a23fefdb8290 /test/CodeGenCXX | |
parent | 6df2408694f81a03eb8b0e3b013272042233c061 (diff) | |
download | FreeBSD-src-4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa.zip FreeBSD-src-4b08eb6308ca90a6c08e2fc79d100821b1b1f6aa.tar.gz |
Update clang to r90226.
Diffstat (limited to 'test/CodeGenCXX')
26 files changed, 908 insertions, 151 deletions
diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp new file mode 100644 index 0000000..a6b74ef --- /dev/null +++ b/test/CodeGenCXX/condition.cpp @@ -0,0 +1,110 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +void *f(); + +template <typename T> T* g() { + if (T* t = f()) + return t; + + return 0; +} + +void h() { + void *a = g<void>(); +} + +struct X { + X(); + ~X(); + operator bool(); +}; + +struct Y { + Y(); + ~Y(); +}; + +void if_destruct(int z) { + // Verify that the condition variable is destroyed at the end of the + // "if" statement. + // CHECK: call void @_ZN1XC1Ev + // CHECK: call zeroext i1 @_ZN1XcvbEv + if (X x = X()) { + // CHECK: store i32 18 + z = 18; + } + // CHECK: call void @_ZN1XD1Ev + // CHECK: store i32 17 + z = 17; + + // CHECK: call void @_ZN1XC1Ev + if (X x = X()) + Y y; + // CHECK: if.then + // CHECK: call void @_ZN1YC1Ev + // CHECK: call void @_ZN1YD1Ev + // CHECK: if.end + // CHECK: call void @_ZN1XD1Ev +} + +struct ConvertibleToInt { + ConvertibleToInt(); + ~ConvertibleToInt(); + operator int(); +}; + +void switch_destruct(int z) { + // CHECK: call void @_ZN16ConvertibleToIntC1Ev + switch (ConvertibleToInt conv = ConvertibleToInt()) { + case 0: + break; + + default: + // CHECK: sw.default: + // CHECK: store i32 19 + z = 19; + break; + } + // CHECK: sw.epilog: + // CHECK: call void @_ZN16ConvertibleToIntD1Ev + // CHECK: store i32 20 + z = 20; +} + +int foo(); + +void while_destruct(int z) { + // CHECK: define void @_Z14while_destructi + // CHECK: while.cond: + while (X x = X()) { + // CHECK: call void @_ZN1XC1Ev + + // CHECK: while.body: + // CHECK: store i32 21 + z = 21; + + // CHECK: while.cleanup: + // CHECK: call void @_ZN1XD1Ev + } + // CHECK: while.end + // CHECK: store i32 22 + z = 22; +} + +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: + // CHECK: call void @_ZN1XC1Ev + // CHECK: for.body: + // CHECK: store i32 23 + z = 23; + // CHECK: for.inc: + // CHECK: br label %for.cond.cleanup + // CHECK: for.cond.cleanup: + // CHECK: call void @_ZN1XD1Ev + // CHECK: for.end: + // CHECK: call void @_ZN1YD1Ev + // CHECK: store i32 24 + z = 24; +} diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp new file mode 100644 index 0000000..f6c466a --- /dev/null +++ b/test/CodeGenCXX/conditional-temporaries.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s + +struct I { + int i; + I(); + ~I(); +}; + +void g(int); + +volatile int i; + +void f1() { + // CHECK: call void @_ZN1IC1Ev + g(i ? I().i : 0); + // CHECK: call void @_Z1gi + // CHECK: call void @_ZN1ID1Ev + + // CHECK: call void @_ZN1IC1Ev + g(i || I().i); + // CHECK: call void @_Z1gi + // CHECK: call void @_ZN1ID1Ev + + // CHECK: call void @_ZN1IC1Ev + g(i && I().i); + // CHECK: call void @_Z1gi + // CHECK: call void @_ZN1ID1Ev +} diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp new file mode 100644 index 0000000..f12c569 --- /dev/null +++ b/test/CodeGenCXX/const-global-linkage.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s + +const int x = 10; +const int y = 20; +// CHECK-NOT: @x +// CHECK: @y = internal constant i32 20 +const int& b() { return y; } + +const char z1[] = "asdf"; +const char z2[] = "zxcv"; +// CHECK-NOT: @z1 +// CHECK: @z2 = internal constant +const char* b2() { return z2; } diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index 427ba53..42da634 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -1,11 +1,26 @@ -// RUN: clang-cc -verify -emit-llvm -o %t %s +// RUN: clang-cc -verify -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s +// CHECK: @a = global i32 10 int a = 10; +// CHECK: @ar = global i32* @a int &ar = a; void f(); +// CHECK: @fr = global void ()* @_Z1fv void (&fr)() = f; struct S { int& a; }; +// CHECK: @s = global %0 { i32* @a } S s = { a }; +// PR5581 +namespace PR5581 { +class C { +public: + enum { e0, e1 }; + unsigned f; +}; + +// CHECK: @_ZN6PR55812g0E = global %1 { i32 1 } +C g0 = { C::e1 }; +} diff --git a/test/CodeGenCXX/copy-assign-synthesis-2.cpp b/test/CodeGenCXX/copy-assign-synthesis-2.cpp new file mode 100644 index 0000000..60d52f5 --- /dev/null +++ b/test/CodeGenCXX/copy-assign-synthesis-2.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm %s -o - | FileCheck %s +struct A {}; +A& (A::*x)(const A&) = &A::operator=; +// CHECK: define linkonce_odr %struct.A* @_ZN1AaSERKS_ diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 3b8f782..2e950eb 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -102,6 +102,17 @@ int main() { m1.pr(); } +struct A { +}; + +struct B : A { + A &a; +}; + +void f(const B &b1) { + B b2(b1); +} + // CHECK-LP64: .globl __ZN1XC1ERKS_ // CHECK-LP64: .weak_definition __ZN1XC1ERKS_ // CHECK-LP64: __ZN1XC1ERKS_: diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp index 5028ce9..71d4baa 100644 --- a/test/CodeGenCXX/default-arguments.cpp +++ b/test/CodeGenCXX/default-arguments.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10 +// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // PR5484 namespace PR5484 { @@ -11,3 +11,59 @@ void g() { f(); } } + +struct A1 { + A1(); + ~A1(); +}; + +struct A2 { + A2(); + ~A2(); +}; + +struct B { + B(const A1& = A1(), const A2& = A2()); +}; + +// CHECK: define void @_Z2f1v() +void f1() { + + // CHECK: call void @_ZN2A1C1Ev( + // CHECK: call void @_ZN2A2C1Ev( + // CHECK: call void @_ZN1BC1ERK2A1RK2A2( + // CHECK: call void @_ZN2A2D1Ev + // CHECK: call void @_ZN2A1D1Ev + B bs[2]; +} + +struct C { + B bs[2]; + C(); +}; + +// CHECK: define void @_ZN1CC1Ev( +// CHECK: call void @_ZN2A1C1Ev( +// CHECK: call void @_ZN2A2C1Ev( +// CHECK: call void @_ZN1BC1ERK2A1RK2A2( +// CHECK: call void @_ZN2A2D1Ev +// CHECK: call void @_ZN2A1D1Ev + +// CHECK: define void @_ZN1CC2Ev( +// CHECK: call void @_ZN2A1C1Ev( +// CHECK: call void @_ZN2A2C1Ev( +// CHECK: call void @_ZN1BC1ERK2A1RK2A2( +// CHECK: call void @_ZN2A2D1Ev +// CHECK: call void @_ZN2A1D1Ev +C::C() { } + +// CHECK: define void @_Z2f3v() +void f3() { + // CHECK: call void @_ZN2A1C1Ev( + // CHECK: call void @_ZN2A2C1Ev( + // CHECK: call void @_ZN1BC1ERK2A1RK2A2( + // CHECK: call void @_ZN2A2D1Ev + // CHECK: call void @_ZN2A1D1Ev + B *bs = new B[2]; + delete bs; +} diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp index 4719f80..0f78fb0 100644 --- a/test/CodeGenCXX/dyncast.cpp +++ b/test/CodeGenCXX/dyncast.cpp @@ -97,7 +97,7 @@ void test1() { // CHECK-LL-NEXT: br i1 %4, label %5, label %9 // CHECK-LL: ; <label>:5 // CHECK-LL-NEXT: %6 = bitcast %class.test1_A* %tmp to i8* -// CHECK-LL-NEXT: %7 = call i8* @__dynamic_cast(i8* %6, i8* bitcast (i8** @_ZTI7test1_B to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1) +// CHECK-LL-NEXT: %7 = call i8* @__dynamic_cast(i8* %6, i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: %8 = bitcast i8* %7 to %class.test1_D* // CHECK-LL-NEXT: br label %10 // CHECK-LL: ; <label>:9 @@ -120,7 +120,7 @@ void test1() { // CHECK-LL-NEXT: br i1 %12, label %13, label %17 // CHECK-LL: ; <label>:13 // CHECK-LL-NEXT: %14 = bitcast %class.test1_A* %tmp6 to i8* -// CHECK-LL-NEXT: %15 = call i8* @__dynamic_cast(i8* %14, i8* bitcast (i8** @_ZTI7test1_B to i8*), i8* bitcast (i8** @_ZTI7test1_A to i8*), i64 -1) +// CHECK-LL-NEXT: %15 = call i8* @__dynamic_cast(i8* %14, i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i64 -1) // CHECK-LL-NEXT: %16 = bitcast i8* %15 to %class.test1_A* // CHECK-LL-NEXT: br label %18 // CHECK-LL: ; <label>:17 @@ -143,7 +143,7 @@ void test1() { // CHECK-LL-NEXT: br i1 %20, label %21, label %25 // CHECK-LL: ; <label>:21 // CHECK-LL-NEXT: %22 = bitcast %class.test1_A* %tmp14 to i8* -// CHECK-LL-NEXT: %23 = call i8* @__dynamic_cast(i8* %22, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_B to i8*), i64 -1) +// CHECK-LL-NEXT: %23 = call i8* @__dynamic_cast({{.*}} %22, i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i64 -1) // CHECK-LL-NEXT: %24 = bitcast i8* %23 to %class.test1_A* // CHECK-LL-NEXT: br label %26 // CHECK-LL: ; <label>:25 @@ -214,7 +214,7 @@ void test1() { // CHECK-LL-NEXT: br i1 %34, label %35, label %39 // CHECK-LL: ; <label>:35 // CHECK-LL-NEXT: %36 = bitcast %class.test1_A* %tmp54 to i8* -// CHECK-LL-NEXT: %37 = call i8* @__dynamic_cast(i8* %36, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1) +// CHECK-LL-NEXT: %37 = call i8* @__dynamic_cast(i8* %36, i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: %38 = bitcast i8* %37 to %class.test1_D* // CHECK-LL-NEXT: br label %40 // CHECK-LL: ; <label>:39 @@ -237,7 +237,7 @@ void test1() { // CHECK-LL-NEXT: br i1 %42, label %43, label %47 // CHECK-LL: ; <label>:43 // CHECK-LL-NEXT: %44 = bitcast %class.test1_A* %tmp63 to i8* -// CHECK-LL-NEXT: %45 = call i8* @__dynamic_cast(i8* %44, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_E to i8*), i64 -1) +// CHECK-LL-NEXT: %45 = call i8* @__dynamic_cast(i8* %44, i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_E to i8*), i64 -1) // CHECK-LL-NEXT: %46 = bitcast i8* %45 to %class.test1_E* // CHECK-LL-NEXT: br label %48 // CHECK-LL: ; <label>:47 @@ -279,7 +279,7 @@ void test1() { // CHECK-LL: if.end85: // CHECK-LL-NEXT: br i1 false, label %50, label %53 // CHECK-LL: ; <label>:50 -// CHECK-LL-NEXT: %51 = call i8* @__dynamic_cast(i8* null, i8* bitcast (i8** @_ZTI7test1_A to i8*), i8* bitcast (i8** @_ZTI7test1_D to i8*), i64 -1) +// CHECK-LL-NEXT: %51 = call i8* @__dynamic_cast(i8* null, i8* bitcast ({{.*}}* @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: %52 = bitcast i8* %51 to %class.test1_D* // CHECK-LL-NEXT: br label %54 // CHECK-LL: ; <label>:53 diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp new file mode 100644 index 0000000..3dd7219 --- /dev/null +++ b/test/CodeGenCXX/eh.cpp @@ -0,0 +1,68 @@ +// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s + +struct test1_D { + double d; +} d1; + +void test1() { + throw d1; +} + +// CHECK: define void @_Z5test1v() nounwind { +// CHECK-NEXT:entry: +// CHECK-NEXT: %exception = call i8* @__cxa_allocate_exception(i64 8) +// CHECK-NEXT: %0 = bitcast i8* %exception to %struct.test1_D* +// CHECK-NEXT: %tmp = bitcast %struct.test1_D* %0 to i8* +// CHECK-NEXT: call void @llvm.memcpy.i64(i8* %tmp, i8* bitcast (%struct.test1_D* @d1 to i8*), i64 8, i32 8) +// CHECK-NEXT: call void @__cxa_throw(i8* %exception, i8* bitcast (%0* @_ZTI7test1_D to i8*), i8* null) noreturn +// CHECK-NEXT: unreachable + + +struct test2_D { + test2_D(const test2_D&o); + test2_D(); + virtual void bar() { } + int i; int j; +} d2; + +void test2() { + throw d2; +} + +// CHECK: define void @_Z5test2v() nounwind { +// CHECK-NEXT:entry: +// CHECK-NEXT: %exception = call i8* @__cxa_allocate_exception(i64 16) +// CHECK-NEXT: %0 = bitcast i8* %exception to %struct.test2_D* +// CHECK-NEXT: call void @_ZN7test2_DC1ERKS_(%struct.test2_D* %0, %struct.test2_D* @d2) +// CHECK-NEXT: call void @__cxa_throw(i8* %exception, i8* bitcast (%0* @_ZTI7test2_D to i8*), i8* null) noreturn +// CHECK-NEXT: unreachable + + +struct test3_D { + test3_D() { } + test3_D(volatile test3_D&o); + virtual void bar(); +}; + +void test3() { + throw (volatile test3_D *)0; +} + +// CHECK: define void @_Z5test3v() nounwind { +// CHECK-NEXT: entry: +// CHECK-NEXT: %exception = call i8* @__cxa_allocate_exception(i64 8) +// CHECK-NEXT: %0 = bitcast i8* %exception to %struct.test3_D** +// CHECK-NEXT: store %struct.test3_D* null, %struct.test3_D** %0 +// CHECK-NEXT: call void @__cxa_throw(i8* %exception, i8* bitcast (%1* @_ZTIPV7test3_D to i8*), i8* null) noreturn +// CHECK-NEXT: unreachable + + +void test4() { + throw; +} + +// CHECK: define void @_Z5test4v() nounwind { +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @__cxa_rethrow() noreturn +// CHECK-NEXT: unreachable diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp new file mode 100644 index 0000000..32ce33d --- /dev/null +++ b/test/CodeGenCXX/mangle-template.cpp @@ -0,0 +1,68 @@ +// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s + +namespace test1 { +int x; +template <int& D> class T { }; +// CHECK: void @_ZN5test12f0ENS_1TILZNS_1xEEEE( +void f0(T<x> a0) {} +} + +namespace test1 { +// CHECK: void @_ZN5test12f0Ef +void f0(float) {} +template<void (&)(float)> struct t1 {}; +// CHECK: void @_ZN5test12f1ENS_2t1ILZNS_2f0EfEEE( +void f1(t1<f0> a0) {} +} + +namespace test2 { +// CHECK: void @_ZN5test22f0Ef +void f0(float) {} +template<void (*)(float)> struct t1 {}; +// FIXME: Fails because we don't treat as an expression. +// CHECK-FIXME: void @_ZN5test22f1ENS_2t1IXadL_ZNS_2f0EfEEEE( +void f1(t1<f0> a0) {} +} + +namespace test3 { +// CHECK: void @test3_f0 +extern "C" void test3_f0(float) {} +template<void (&)(float)> struct t1 {}; +// FIXME: Fails because we tack on a namespace. +// CHECK-FIXME: void @_ZN5test32f1ENS_2t1ILZ8test3_f0EEE( +void f1(t1<test3_f0> a0) {} +} + +namespace test4 { +// CHECK: void @test4_f0 +extern "C" void test4_f0(float) {} +template<void (*)(float)> struct t1 {}; +// FIXME: Fails because we don't treat as an expression. +// CHECK-FIXME: void @_ZN5test42f1ENS_2t1IXadL_Z8test4_f0EEEE( +void f1(t1<test4_f0> a0) {} +} + +// CHECK: void @test5_f0 +extern "C" void test5_f0(float) {} +int main(int) {} + +namespace test5 { +template<void (&)(float)> struct t1 {}; +// CHECK: void @_ZN5test52f1ENS_2t1ILZ8test5_f0EEE( +void f1(t1<test5_f0> a0) {} + +template<int (&)(int)> struct t2 {}; +// CHECK: void @_ZN5test52f2ENS_2t2ILZ4mainEEE +void f2(t2<main> a0) {} +} + +// FIXME: This fails. +namespace test6 { +struct A { void im0(float); }; +// CHECK: void @_ZN5test61A3im0Ef +void A::im0(float) {} +template <void(A::*)(float)> class T { }; +// FIXME: Fails because we don't treat as an expression. +// CHECK-FAIL: void @_ZN5test62f0ENS_1TIXadL_ZNS_1A3im0EfEEEE( +void f0(T<&A::im0> a0) {} +} diff --git a/test/CodeGenCXX/member-expressions.cpp b/test/CodeGenCXX/member-expressions.cpp index f90b807..a38d5f9 100644 --- a/test/CodeGenCXX/member-expressions.cpp +++ b/test/CodeGenCXX/member-expressions.cpp @@ -17,3 +17,30 @@ void f() } } + +struct A { + A(); + ~A(); + enum E { Foo }; +}; + +A *g(); + +void f(A *a) { + A::E e1 = a->Foo; + + // CHECK: call %struct.A* @_Z1gv() + A::E e2 = g()->Foo; + // CHECK: call void @_ZN1AC1Ev( + // CHECK: call void @_ZN1AD1Ev( + A::E e3 = A().Foo; +} + +namespace test3 { +struct A { + static int foo(); +}; +int f() { + return A().foo(); +} +} diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index 7792560..05bf396 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -34,6 +34,11 @@ void f() { // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 16 // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pc, i32 0, i32 1) pc = pa; + + // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0) + // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 16 + // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pa, i32 0, i32 1) + pa = static_cast<void (A::*)()>(pc); } void f2() { @@ -55,6 +60,10 @@ void f3(A *a, A &ar) { (ar.*pa)(); } +bool f4() { + return pa; +} + // PR5177 namespace PR5177 { struct A { @@ -87,3 +96,12 @@ namespace PR5138 { void (foo::*ptr3)(void) = (void (foo::*)(void))&foo::bar; } + +// PR5593 +namespace PR5593 { + struct A { }; + + bool f(void (A::*f)()) { + return f && f; + } +} diff --git a/test/CodeGenCXX/member-pointer-cast.cpp b/test/CodeGenCXX/member-pointer-cast.cpp new file mode 100644 index 0000000..7949968 --- /dev/null +++ b/test/CodeGenCXX/member-pointer-cast.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc %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-templates.cpp b/test/CodeGenCXX/member-templates.cpp new file mode 100644 index 0000000..c8494c4 --- /dev/null +++ b/test/CodeGenCXX/member-templates.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: ; ModuleID +struct A { + template<typename T> + A(T); +}; + +template<typename T> A::A(T) {} + +struct B { + template<typename T> + B(T); +}; + +template<typename T> B::B(T) {} + +// CHECK: define void @_ZN1BC1IiEET_(%struct.B* %this, i32) +// CHECK: define void @_ZN1BC2IiEET_(%struct.B* %this, i32) +template B::B(int); + +template<typename T> +struct C { + void f() { + int a[] = { 1, 2, 3 }; + } +}; + +void f(C<int>& c) { + c.f(); +} diff --git a/test/CodeGenCXX/new-with-default-arg.cpp b/test/CodeGenCXX/new-with-default-arg.cpp new file mode 100644 index 0000000..b73b7f08 --- /dev/null +++ b/test/CodeGenCXX/new-with-default-arg.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -emit-llvm -o - %s +// pr5547 + +struct A { + void* operator new(__typeof(sizeof(int))); + A(); +}; + +A* x() { + return new A; +} + +struct B { + void* operator new(__typeof(sizeof(int)), int = 1, int = 4); + B(float); +}; + +B* y() { + new (3,4) B(1); + return new(1) B(2); +} + +struct C { + void* operator new(__typeof(sizeof(int)), int, int = 4); + C(); +}; + +C* z() { + new (3,4) C; + return new(1) C; +} + + diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 3f191de..13f26b2 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s +// RUN: clang-cc -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s #include <stddef.h> void t1() { @@ -72,3 +72,21 @@ void t8(int n) { new U[10]; new U[n]; } + +void t9() { + bool b; + + new bool(true); + new (&b) bool(true); +} + +struct A { + void* operator new(__typeof(sizeof(int)), int, float, ...); + A(); +}; + +A* t10() { + // CHECK: @_ZN1AnwEmifz + return new(1, 2, 3.45, 100) A; +} + diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 8e0e1cb..eaaf346 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -136,3 +136,8 @@ void f(int &a) { (a = 10) = 20; } } + +// PR5590 +struct s0; +struct s1 { struct s0 &s0; }; +void f0(s1 a) { s1 b = a; } diff --git a/test/CodeGenCXX/temp-1.cpp b/test/CodeGenCXX/temp-1.cpp deleted file mode 100644 index 9b97f00..0000000 --- a/test/CodeGenCXX/temp-1.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 && -struct A { - A(); - ~A(); - void f(); -}; - -// RUN: grep "call void @_ZN1AC1Ev" %t | count 2 && -// RUN: grep "call void @_ZN1AD1Ev" %t | count 2 && -void f1() { - (void)A(); - A().f(); -} - -// Function calls -struct B { - B(); - ~B(); -}; - -B g(); - -// RUN: grep "call void @_ZN1BC1Ev" %t | count 0 && -// RUN: grep "call void @_ZN1BD1Ev" %t | count 1 && -void f2() { - (void)g(); -} - -// Member function calls -struct C { - C(); - ~C(); - - C f(); -}; - -// RUN: grep "call void @_ZN1CC1Ev" %t | count 1 && -// RUN: grep "call void @_ZN1CD1Ev" %t | count 2 && -void f3() { - C().f(); -} - -// Function call operator -struct D { - D(); - ~D(); - - D operator()(); -}; - -// RUN: grep "call void @_ZN1DC1Ev" %t | count 1 && -// RUN: grep "call void @_ZN1DD1Ev" %t | count 2 && -void f4() { - D()(); -} - -// Overloaded operators -struct E { - E(); - ~E(); - E operator+(const E&); - E operator!(); -}; - -// RUN: grep "call void @_ZN1EC1Ev" %t | count 3 && -// RUN: grep "call void @_ZN1ED1Ev" %t | count 5 && -void f5() { - E() + E(); - !E(); -} - -struct F { - F(); - ~F(); - F& f(); -}; - -// RUN: grep "call void @_ZN1FC1Ev" %t | count 1 && -// RUN: grep "call void @_ZN1FD1Ev" %t | count 1 -void f6() { - F().f(); -} - diff --git a/test/CodeGenCXX/temp-order.cpp b/test/CodeGenCXX/temp-order.cpp new file mode 100644 index 0000000..ecf075f --- /dev/null +++ b/test/CodeGenCXX/temp-order.cpp @@ -0,0 +1,199 @@ +// Output file should have no calls to error() with folding. +// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s +// RUN: FileCheck %s < %t + +static unsigned pow(unsigned Base, unsigned Power) { + unsigned Val = 1; + while (Power--) + Val *= Base; + return Val; +} + +struct TempTracker { + unsigned Product, Index; + + TempTracker() : Product(1), Index(0) {} + +}; + +// FIXME: This can be used to check elision as well, if P = 0 hacks are removed. +struct A { + TempTracker &TT; + mutable unsigned P; + bool Truth; + + A(TempTracker &_TT, unsigned _P, bool _Truth = true) + : TT(_TT), P(_P), Truth(_Truth) {} + A(const A &RHS) : TT(RHS.TT), P(RHS.P), Truth(RHS.Truth) { RHS.P = 0; } + ~A() { + if (P) + TT.Product *= pow(P, ++TT.Index); + } + + A &operator=(const A &RHS) { + TT = RHS.TT; + P = RHS.P; + Truth = RHS.Truth; + RHS.P = 0; + return *this; + } + + operator bool () { return Truth; } +}; + +// 3, 7, 2 +static unsigned f0(bool val = false) { + TempTracker tt; + { + A a(tt, 2); + if ((A(tt, 3), val)) + A b(tt, 5); + A c(tt, 7); + } + return tt.Product; +} + +// 3, 5, 7, 2 +static unsigned f1(bool val = true) { + TempTracker tt; + { + A a(tt, 2); + if ((A(tt, 3), val)) + A b(tt, 5); + A c(tt, 7); + } + return tt.Product; +} + +// 5, 3, 7, 2 +static unsigned f2() { + TempTracker tt; + { + A a(tt, 2); + if (A b = A(tt, 3)) + A c(tt, 5); + A d(tt, 7); + } + return tt.Product; +} + +// 7, 3, 11, 2 +static unsigned f3() { + TempTracker tt; + { + A a(tt, 2); + if (A b = A(tt, 3, false)) + A c(tt, 5); + else + A c(tt, 7); + A d(tt, 11); + } + return tt.Product; +} + +// 3, 7, 2 +static unsigned f4() { + TempTracker tt; + { + A a(tt, 2); + while (A b = A(tt, 3, false)) + A c(tt, 5); + A c(tt, 7); + } + return tt.Product; +} + +// 5, 3, 7, 2 +static unsigned f5() { + TempTracker tt; + { + A a(tt, 2); + while (A b = A(tt, 3, true)) { + A c(tt, 5); + break; + } + A c(tt, 7); + } + return tt.Product; +} + +// 3, 7, 11, 5, 13, 2 +static unsigned f6() { + TempTracker tt; + { + A a(tt, 2); + for (A b = (A(tt, 3), A(tt, 5)), c = (A(tt, 7), A(tt, 11));;) + break; + A c(tt, 13); + } + 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 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)) +void test() { +// CHECK: call void @print(i8* {{.*}}, i32 1176) + print("f0", f0()); + if (f0() != ORDER3(3, 7, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 411600) + print("f1", f1()); + if (f1() != ORDER4(3, 5, 7, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 246960) + print("f2", f2()); + if (f2() != ORDER4(5, 3, 7, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 1341648) + print("f3", f3()); + if (f3() != ORDER4(7, 3, 11, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 1176) + print("f4", f4()); + if (f4() != ORDER3(3, 7, 2)) + error(); + +// CHECK: call void @print(i8* {{.*}}, i32 246960) + print("f5", f5()); + if (f5() != ORDER4(5, 3, 7, 2)) + error(); + +// FIXME: Clang/LLVM currently can't fold this to a constant. If the error check +// is present (since it avoids single-caller inlining). PR5645. + +// CHECK: call void @print(i8* {{.*}}, i32 1251552576) + print("f6", f6()); +// if (f6() != ORDER6(3, 7, 11, 5, 13, 2)) +// error(); +} + + + +#ifdef HARNESS + +#include <cstdlib> +#include <cstdio> + +extern "C" void error() { + abort(); +} + +extern "C" void print(const char *name, unsigned N) { + printf("%s: %d\n", name, N); +} + +int main() { + test(); + return 0; +} + +#endif diff --git a/test/CodeGenCXX/virt-dtor-key.cpp b/test/CodeGenCXX/virt-dtor-key.cpp new file mode 100644 index 0000000..30f3563 --- /dev/null +++ b/test/CodeGenCXX/virt-dtor-key.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -emit-llvm %s -o - | FileCheck %s +// CHECK: @_ZTI3foo = linkonce_odr constant +class foo { + foo(); + virtual ~foo(); +}; + +foo::~foo() { +} diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index b453ed5..7135aaf 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -4,6 +4,11 @@ // RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t-64.ll // RUN: FileCheck -check-prefix LPLL64 --input-file=%t-64.ll %s + +// CHECK-LP64: main: +// CHECK-LP64: movl $1, 12(%rax) +// CHECK-LP64: movl $2, 8(%rax) + struct B { virtual void bar1(); virtual void bar2(); @@ -12,6 +17,12 @@ struct B { void B::bar1() { } void B::bar2() { } +// CHECK-LP64: __ZTV1B: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI1B +// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev +// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev + struct C { virtual void bee1(); virtual void bee2(); @@ -41,6 +52,28 @@ public: }; void F::foo() { } +// CHECK-LP64: __ZTV1F: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad 16 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI1F +// CHECK-LP64-NEXT: .quad __ZN1D3booEv +// CHECK-LP64-NEXT: .quad __ZN1F3fooEv +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad 18446744073709551600 +// CHECK-LP64-NEXT: .quad __ZTI1F +// CHECK-LP64-NEXT: .quad __ZN2D13barEv +// CHECK-LP64-NEXT: .quad __ZN2D14bar2Ev +// CHECK-LP64-NEXT: .quad __ZN2D14bar3Ev +// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev +// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev + + int j; void *vp; void test2() { @@ -79,9 +112,18 @@ int main() { ap->b = 2; } -// CHECK-LP64: main: -// CHECK-LP64: movl $1, 12(%rax) -// CHECK-LP64: movl $2, 8(%rax) +// CHECK-LP64: __ZTV1A: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI1A +// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev +// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev +// CHECK-LP64-NEXT: .quad __ZN1A4foo1Ev +// CHECK-LP64-NEXT: .quad __ZN1A4foo2Ev +// CHECK-LP64-NEXT: .quad 18446744073709551600 +// CHECK-LP64-NEXT: .quad __ZTI1A +// CHECK-LP64-NEXT: .quad __ZN1C4bee1Ev +// CHECK-LP64-NEXT: .quad __ZN1C4bee2Ev + struct test12_A { virtual void foo0() { } @@ -675,12 +717,10 @@ virtual void foo_B2() { } }; struct test16_D : test16_NV1, virtual test16_B2 { - virtual void bar(); - virtual test16_D *foo1(); + virtual void bar() { } + virtual test16_D *foo1() { return 0; } }; -void test16_D::bar() { } - // CHECK-LP64: __ZTV8test16_D: // CHECK-LP64-NEXT: .quad 32 // CHECK-LP64-NEXT: .quad 16 @@ -1040,45 +1080,6 @@ class test21_D : public test21_B, public test21_B1 { -// CHECK-LP64: __ZTV1B: -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .quad __ZTI1B -// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev -// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev - -// CHECK-LP64: __ZTV1A: -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .quad __ZTI1A -// CHECK-LP64-NEXT: .quad __ZN1B4bar1Ev -// CHECK-LP64-NEXT: .quad __ZN1B4bar2Ev -// CHECK-LP64-NEXT: .quad __ZN1A4foo1Ev -// CHECK-LP64-NEXT: .quad __ZN1A4foo2Ev -// CHECK-LP64-NEXT: .quad 18446744073709551600 -// CHECK-LP64-NEXT: .quad __ZTI1A -// CHECK-LP64-NEXT: .quad __ZN1C4bee1Ev -// CHECK-LP64-NEXT: .quad __ZN1C4bee2Ev - -// CHECK-LP64: __ZTV1F: -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .quad 16 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .quad __ZTI1F -// CHECK-LP64-NEXT: .quad __ZN1D3booEv -// CHECK-LP64-NEXT: .quad __ZN1F3fooEv -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .space 8 -// CHECK-LP64-NEXT: .quad 18446744073709551600 -// CHECK-LP64-NEXT: .quad __ZTI1F -// CHECK-LP64-NEXT: .quad __ZN2D13barEv -// CHECK-LP64-NEXT: .quad __ZN2D14bar2Ev -// CHECK-LP64-NEXT: .quad __ZN2D14bar3Ev -// CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev -// CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev - test21_D d21; test20_D d20; test19_D d19; diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp index a825120..eae868f 100644 --- a/test/CodeGenCXX/virtual-base-cast.cpp +++ b/test/CodeGenCXX/virtual-base-cast.cpp @@ -1,9 +1,33 @@ -// RUN: clang-cc -emit-llvm-only %s +// RUN: clang-cc -emit-llvm %s -o - -triple i686-pc-linux-gnu | FileCheck %s -struct A { virtual ~A(); }; -struct B : A { virtual ~B(); }; -struct C : virtual B { virtual ~C(); }; +struct A { int a; virtual int aa(); }; +struct B { int b; virtual int bb(); }; +struct C : virtual A, virtual B { int c; virtual int aa(); virtual int bb(); }; +struct AA { int a; virtual int aa(); }; +struct BB { int b; virtual int bb(); }; +struct CC : AA, BB { virtual int aa(); virtual int bb(); virtual int cc(); }; +struct D : virtual C, virtual CC { int e; }; -void f(C *c) { - A* a = c; -} +D* x; + +A* a() { return x; } +// CHECK: @_Z1av() nounwind +// CHECK: [[VBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -16 +// CHECK: [[CASTVBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRA]] to i32* +// CHECK: load i32* [[CASTVBASEOFFSETPTRA]] +// CHECK: } + +B* b() { return x; } +// CHECK: @_Z1bv() nounwind +// CHECK: [[VBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -20 +// CHECK: [[CASTVBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRA]] to i32* +// CHECK: load i32* [[CASTVBASEOFFSETPTRA]] +// CHECK: } + +BB* c() { return x; } +// CHECK: @_Z1cv() nounwind +// CHECK: [[VBASEOFFSETPTRC:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -24 +// CHECK: [[CASTVBASEOFFSETPTRC:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRC]] to i32* +// CHECK: [[VBASEOFFSETC:%[a-zA-Z0-9\.]+]] = load i32* [[CASTVBASEOFFSETPTRC]] +// CHECK: add i32 [[VBASEOFFSETC]], 8 +// CHECK: } diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp new file mode 100644 index 0000000..e791758 --- /dev/null +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -0,0 +1,19 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s + +struct basic_ios{~basic_ios(); }; + +template<typename _CharT> struct basic_istream : virtual public basic_ios { + virtual ~basic_istream(){} +}; + +template<typename _CharT> struct basic_iostream : public basic_istream<_CharT> +{ + virtual ~basic_iostream(){} +}; + +basic_iostream<char> res; + +int main() { +} + +// CHECK: call void @_ZN9basic_iosD2Ev diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp new file mode 100644 index 0000000..4b069ea --- /dev/null +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s + +struct A { + A(); +}; + +// CHECK: define void @_ZN1AC1Ev(%struct.A* %this) +// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) +A::A() { } + +struct B : virtual A { + B(); +}; + +// CHECK: define void @_ZN1BC1Ev(%struct.B* %this) +// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) +B::B() { } diff --git a/test/CodeGenCXX/virtual-functions-incomplete-types.cpp b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp new file mode 100644 index 0000000..1e1e962 --- /dev/null +++ b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct A; + +struct B { + virtual void f(); + virtual A g(); +}; + +void B::f() { } + +// CHECK: declare void @_ZN1B1gEv() + +struct C; + +struct D { + virtual void f(); + virtual C g(); +}; + +void D::f() { } + +struct C { + int a; +}; + +// CHECK: define i64 @_ZN1D1gEv(%struct.B* %this) +C D::g() { + return C(); +} diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 6b5e7a7..0e4c2ab 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -1,9 +1,24 @@ -// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s -struct A { ~A(); }; +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// RUN: grep 'define void @_Z2f11A(.struct.A\* .a)' %t -void f1(A a) { } +// CHECK: [[i64_i64_ty:%.*]] = type { i64, i64 } +// CHECK: [[i64_double_ty:%.*]] = type { i64, double } + +// Basic base class test. +struct f0_s0 { unsigned a; }; +struct f0_s1 : public f0_s0 { void *b; }; +// CHECK: define void @_Z2f05f0_s1([[i64_i64_ty]]) +void f0(f0_s1 a0) { } + +// Check with two eight-bytes in base class. +struct f1_s0 { unsigned a; unsigned b; float c; }; +struct f1_s1 : public f1_s0 { float d;}; +// CHECK: define void @_Z2f15f1_s1([[i64_double_ty]]) +void f1(f1_s1 a0) { } + +// Check with two eight-bytes in base class and merge. +struct f2_s0 { unsigned a; unsigned b; float c; }; +struct f2_s1 : public f2_s0 { char d;}; +// CHECK: define void @_Z2f25f2_s1([[i64_i64_ty]]) +void f2(f2_s1 a0) { } -// RUN: grep 'define void @_Z2f2v(.struct.A\* noalias sret .agg.result)' %t -A f2() { return A(); } |