summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r--test/CodeGenCXX/condition.cpp110
-rw-r--r--test/CodeGenCXX/conditional-temporaries.cpp28
-rw-r--r--test/CodeGenCXX/const-global-linkage.cpp13
-rw-r--r--test/CodeGenCXX/const-init.cpp17
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-2.cpp4
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp11
-rw-r--r--test/CodeGenCXX/default-arguments.cpp58
-rw-r--r--test/CodeGenCXX/dyncast.cpp12
-rw-r--r--test/CodeGenCXX/eh.cpp68
-rw-r--r--test/CodeGenCXX/mangle-template.cpp68
-rw-r--r--test/CodeGenCXX/member-expressions.cpp27
-rw-r--r--test/CodeGenCXX/member-function-pointers.cpp18
-rw-r--r--test/CodeGenCXX/member-pointer-cast.cpp21
-rw-r--r--test/CodeGenCXX/member-templates.cpp31
-rw-r--r--test/CodeGenCXX/new-with-default-arg.cpp33
-rw-r--r--test/CodeGenCXX/new.cpp20
-rw-r--r--test/CodeGenCXX/references.cpp5
-rw-r--r--test/CodeGenCXX/temp-1.cpp83
-rw-r--r--test/CodeGenCXX/temp-order.cpp199
-rw-r--r--test/CodeGenCXX/virt-dtor-key.cpp9
-rw-r--r--test/CodeGenCXX/virt.cpp93
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp38
-rw-r--r--test/CodeGenCXX/virtual-base-destructor-call.cpp19
-rw-r--r--test/CodeGenCXX/virtual-bases.cpp17
-rw-r--r--test/CodeGenCXX/virtual-functions-incomplete-types.cpp30
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp27
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(); }
OpenPOWER on IntegriCloud