Abstract IR generation of array cookies into the C++ ABI class and
implement ARM array cookies.  Also fix a few unfortunate bugs:
  - throwing dtors in deletes prevented the allocation from being deleted
  - adding the cookie to the new[] size was not being considered for
    overflow (and, more seriously, was screwing up the earlier checks)
  - deleting an array via a pointer to array of class type was not
    causing any destructors to be run and was passing the unadjusted
    pointer to the deallocator
  - lots of address-space problems, in case anyone wants to support
    free store in a variant address space :)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112814 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index b4c8c83..fb962e0 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 - -fexceptions | 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:
@@ -88,6 +90,153 @@
     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;
+  }
+}
+
   // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
   // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
   // CHECK:   ret [[C]]* undef
@@ -95,7 +244,6 @@
   // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
   // CHECK:   call void @_ZN5test21CD0Ev(
   // CHECK:   ret void
-}
 
 // CHECK: @_GLOBAL__D_a()
 // CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)