aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/arm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/arm.cpp')
-rw-r--r--test/CodeGenCXX/arm.cpp274
1 files changed, 272 insertions, 2 deletions
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 1d4085ca231d..44c0affa5a8f 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
+
+typedef typeof(sizeof(int)) size_t;
class foo {
public:
@@ -13,7 +15,275 @@ public:
// The global dtor needs the right calling conv with -fno-use-cxa-atexit
// rdar://7817590
+// Checked at end of file.
bar baz;
+// Destructors and constructors must return this.
+namespace test1 {
+ void foo();
+
+ struct A {
+ A(int i) { foo(); }
+ ~A() { foo(); }
+ void bar() { foo(); }
+ };
+
+ // CHECK: define void @_ZN5test14testEv()
+ void test() {
+ // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
+ // CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
+ // CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]])
+ // CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]])
+ // CHECK: ret void
+ A a = 10;
+ a.bar();
+ }
+
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]*
+ // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
+ // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
+ // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
+ // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
+ // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
+ // CHECK: call [[A]]* @_ZN5test11AC2Ei(
+ // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
+ // CHECK: ret [[A]]* [[THIS2]]
+
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]*
+ // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
+ // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
+ // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
+ // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
+ // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
+ // CHECK: call [[A]]* @_ZN5test11AD2Ev(
+ // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
+ // CHECK: ret [[A]]* [[THIS2]]
+}
+
+// Awkward virtual cases.
+namespace test2 {
+ void foo();
+
+ struct A {
+ int x;
+
+ A(int);
+ virtual ~A() { foo(); }
+ };
+
+ struct B {
+ int y;
+ int z;
+
+ B(int);
+ virtual ~B() { foo(); }
+ };
+
+ struct C : A, virtual B {
+ int q;
+
+ C(int i) : A(i), B(i) { foo(); }
+ ~C() { foo(); }
+ };
+
+ void test() {
+ C c = 10;
+ }
+
+ // Tests at eof
+}
+
+namespace test3 {
+ struct A {
+ int x;
+ ~A();
+ };
+
+ void a() {
+ // CHECK: define void @_ZN5test31aEv()
+ // CHECK: call noalias i8* @_Znam(i32 48)
+ // CHECK: store i32 4
+ // CHECK: store i32 10
+ A *x = new A[10];
+ }
+
+ void b(int n) {
+ // CHECK: define void @_ZN5test31bEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[N]]
+ A *x = new A[n];
+ }
+
+ void c() {
+ // CHECK: define void @_ZN5test31cEv()
+ // CHECK: call noalias i8* @_Znam(i32 808)
+ // CHECK: store i32 4
+ // CHECK: store i32 200
+ A (*x)[20] = new A[10][20];
+ }
+
+ void d(int n) {
+ // CHECK: define void @_ZN5test31dEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[NE]]
+ A (*x)[20] = new A[n][20];
+ }
+
+ void e(A *x) {
+ // CHECK: define void @_ZN5test31eEPNS_1AE(
+ // CHECK: icmp eq {{.*}}, null
+ // CHECK: getelementptr {{.*}}, i64 -8
+ // CHECK: getelementptr {{.*}}, i64 4
+ // CHECK: bitcast {{.*}} to i32*
+ // CHECK: load
+ // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
+ // CHECK: call void @_ZdaPv
+ delete [] x;
+ }
+
+ void f(A (*x)[20]) {
+ // CHECK: define void @_ZN5test31fEPA20_NS_1AE(
+ // CHECK: icmp eq {{.*}}, null
+ // CHECK: getelementptr {{.*}}, i64 -8
+ // CHECK: getelementptr {{.*}}, i64 4
+ // CHECK: bitcast {{.*}} to i32*
+ // CHECK: load
+ // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
+ // CHECK: call void @_ZdaPv
+ delete [] x;
+ }
+}
+
+namespace test4 {
+ struct A {
+ int x;
+ void operator delete[](void *, size_t sz);
+ };
+
+ void a() {
+ // CHECK: define void @_ZN5test41aEv()
+ // CHECK: call noalias i8* @_Znam(i32 48)
+ // CHECK: store i32 4
+ // CHECK: store i32 10
+ A *x = new A[10];
+ }
+
+ void b(int n) {
+ // CHECK: define void @_ZN5test41bEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[N]]
+ A *x = new A[n];
+ }
+
+ void c() {
+ // CHECK: define void @_ZN5test41cEv()
+ // CHECK: call noalias i8* @_Znam(i32 808)
+ // CHECK: store i32 4
+ // CHECK: store i32 200
+ A (*x)[20] = new A[10][20];
+ }
+
+ void d(int n) {
+ // CHECK: define void @_ZN5test41dEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[NE]]
+ A (*x)[20] = new A[n][20];
+ }
+
+ void e(A *x) {
+ // CHECK: define void @_ZN5test41eEPNS_1AE(
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
+ // CHECK: getelementptr inbounds {{.*}}, i64 4
+ // CHECK: bitcast
+ // CHECK: [[T0:%.*]] = load i32*
+ // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
+ // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
+ // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
+ delete [] x;
+ }
+
+ void f(A (*x)[20]) {
+ // CHECK: define void @_ZN5test41fEPA20_NS_1AE(
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
+ // CHECK: getelementptr inbounds {{.*}}, i64 4
+ // CHECK: bitcast
+ // CHECK: [[T0:%.*]] = load i32*
+ // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
+ // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
+ // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
+ delete [] x;
+ }
+}
+
+// <rdar://problem/8386802>: don't crash
+namespace test5 {
+ struct A {
+ ~A();
+ };
+
+ // CHECK: define void @_ZN5test54testEPNS_1AE
+ void test(A *a) {
+ // CHECK: [[PTR:%.*]] = alloca [[A:%.*]]*, align 4
+ // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4
+ // CHECK-NEXT: [[TMP:%.*]] = load [[A]]** [[PTR]], align 4
+ // CHECK-NEXT: call [[A]]* @_ZN5test51AD1Ev([[A]]* [[TMP]])
+ // CHECK-NEXT: ret void
+ a->~A();
+ }
+}
+
+namespace test6 {
+ struct A {
+ virtual ~A();
+ };
+
+ // CHECK: define void @_ZN5test64testEPNS_1AE
+ void test(A *a) {
+ // CHECK: [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4
+ // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null
+ // CHECK-NEXT: br i1 [[ISNULL]]
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)***
+ // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1
+ // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]]
+ // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]])
+ // CHECK-NEXT: br label
+ // CHECK: ret void
+ delete a;
+ }
+}
+
+ // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
+ // CHECK: call [[C]]* @_ZN5test21CD1Ev(
+ // CHECK: ret [[C]]* undef
+
+ // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
+ // CHECK: call void @_ZN5test21CD0Ev(
+ // CHECK: ret void
+
// CHECK: @_GLOBAL__D_a()
-// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz)
+// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)