[ms-cxxabi] Use inalloca on win32 when passing non-trivial C++ objects

When a non-trivial parameter is present, clang now gathers up all the
parameters that lack inreg and puts them into a packed struct.  MSVC
always aligns each parameter to 4 bytes and no more, so this is a pretty
simple struct to lay out.

On win64, non-trivial records are passed indirectly.  Prior to this
change, clang was incorrectly using byval on win64.

I'm able to self-host a working clang with this change and additional
LLVM patches.

Reviewers: rsmith

Differential Revision: http://llvm-reviews.chandlerc.com/D2636

llvm-svn: 200597
diff --git a/clang/test/CodeGenCXX/copy-constructor-elim.cpp b/clang/test/CodeGenCXX/copy-constructor-elim.cpp
index ad3a87b..8e9bee9 100644
--- a/clang/test/CodeGenCXX/copy-constructor-elim.cpp
+++ b/clang/test/CodeGenCXX/copy-constructor-elim.cpp
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 -emit-llvm -o %t %s
-// RUN: not grep "_ZN1CC1ERK1C" %t
-// RUN: not grep "_ZN1SC1ERK1S" %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix MS
+// CHECK-NOT: _ZN1CC1ERK1C
+// CHECK-NOT: _ZN1SC1ERK1S
+// MS-NOT: ?0C@@QAE@ABV0
+// MS-NOT: ?0S@@QAE@ABV0
 
 extern "C" int printf(...);
 
diff --git a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index 4415c2e..dff52ae 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -12,7 +12,10 @@
 // Order of destruction should be left to right.
 //
 // CHECK-LABEL: define void @"\01?foo@@YAXUA@@00@Z"
-// CHECK:              ({{.*}} %[[a:.*]], {{.*}} %[[b:.*]], {{.*}} %[[c:.*]])
+// CHECK:          ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca)
+// CHECK: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 0
+// CHECK: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 1
+// CHECK: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 2
 // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]])
 // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[b]])
 // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]])
@@ -27,10 +30,16 @@
 // things as we unwind.
 //
 // CHECK-LABEL: define void @"\01?call_foo@@YAXXZ"()
-// CHECK: call   x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3:.*]], i32 3)
-// CHECK: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2:.*]], i32 2)
-// CHECK: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1:.*]], i32 1)
-// CHECK: call void @"\01?foo@@YAXUA@@00@Z"({{.*}} %[[arg1]], {{.*}} %[[arg2]], {{.*}} %[[arg3]])
+// CHECK: call i8* @llvm.stacksave()
+// CHECK: %[[argmem:[^ ]*]] = alloca [[argmem_ty]], inalloca
+// CHECK: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 2
+// CHECK: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
+// CHECK: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// CHECK: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
+// CHECK: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
+// CHECK: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
+// CHECK: invoke void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// CHECK: call void @llvm.stackrestore
 // CHECK: ret void
 //
 //   lpad2:
diff --git a/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
new file mode 100644
index 0000000..00d36b7
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
+
+struct A {
+  A() : a(42) {}
+  A(const A &o) : a(o.a) {}
+  ~A() {}
+  int a;
+  A foo(A o);
+};
+
+A A::foo(A x) {
+  A y(*this);
+  y.a += x.a;
+  return y;
+}
+
+// CHECK: define x86_thiscallcc void @"\01?foo@A@@QAE?AU1@U1@@Z"
+// CHECK:       (%struct.A* %this, <{ %struct.A*, %struct.A }>* inalloca)
+
+int main() {
+  A x;
+  A y = x.foo(x);
+}
+
+// CHECK: call x86_thiscallcc void @"\01?foo@A@@QAE?AU1@U1@@Z"
+// CHECK:       (%struct.A* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
diff --git a/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
new file mode 100644
index 0000000..3361921
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
+
+#include <stdarg.h>
+
+struct A {
+  A(int a) : a(a) {}
+  A(const A &o) : a(o.a) {}
+  ~A() {}
+  int a;
+};
+
+int foo(A a, ...) {
+  va_list ap;
+  va_start(ap, a);
+  int sum = 0;
+  for (int i = 0; i < a.a; ++i)
+    sum += va_arg(ap, int);
+  va_end(ap);
+  return sum;
+}
+
+int main() {
+  return foo(A(3), 1, 2, 3);
+}
+// CHECK-LABEL: define i32 @main()
+// CHECK: %[[argmem_cast:[^ ]*]] = bitcast <{ %struct.A, i32, i32, i32 }>* %argmem to <{ %struct.A }>*
+// CHECK: call i32 (<{ %struct.A }>*, ...)* @"\01?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca %[[argmem_cast]])
diff --git a/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp
index 6731c0e..ecce71d 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp
@@ -14,17 +14,21 @@
 }
 
 // With exceptions, we need to clean up at least one of these temporaries.
-// WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
-//    First one doesn't have any cleanups, no need for invoke.
-// WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
+// WIN32:   %[[base:.*]] = call i8* @llvm.stacksave()
+//    If this call throws, we have to restore the stack.
+// WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
 //    If this call throws, we have to cleanup the first temporary.
 // WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
-//    If this call throws, we already popped our cleanups
-// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+//    If this call throws, we have to cleanup the stacksave.
+// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32:   call void @llvm.stackrestore(i8* %[[base]])
 // WIN32:   ret void
 //
 //    There should be one dtor call for unwinding from the second getA.
 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32-NOT: @"\01??1A@@QAE@XZ"
+// WIN32:   call void @llvm.stackrestore
 // WIN32: }
 
 void TakeRef(const A &a);
@@ -32,20 +36,28 @@
   return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
 }
 
-// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
+// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
 // WIN32:   %[[isactive:.*]] = alloca i1
-// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32:   call i8* @llvm.stacksave()
+// WIN32:   %[[argmem:.*]] = alloca [[argmem_ty:<{ %struct.A, %struct.A }>]], inalloca
+// WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
+//
+// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
 // WIN32:   store i1 true, i1* %[[isactive]]
+//
+// WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   store i1 false, i1* %[[isactive]]
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+//
+// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32:   call void @llvm.stackrestore
 //        Destroy the two const ref temporaries.
 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32:   ret i32
 //
 //        Conditionally destroy arg1.
@@ -60,20 +72,22 @@
   return (cond ? TakesTwo(A(), A()) : CouldThrow());
 }
 
-// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
+// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
 // WIN32:   store i1 false
 // WIN32:   br i1
-//        No cleanups, so we call and then activate a cleanup if it succeeds.
-// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
-// WIN32:   store i1 true
-//        Now we have a cleanup for the first aggregate, so we invoke.
+// WIN32:   call i8* @llvm.stacksave()
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
-//        Now we have no cleanups because TakeTwo will destruct both args.
-// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
-//        Still no cleanups, so call.
+// WIN32:   store i1 true
+// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32:   call void @llvm.stackrestore
+//
 // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
-//        Somewhere in the landing pad for our single invoke, call the dtor.
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+//
+//        Only one dtor in the invoke for arg1
+// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32:   call void @llvm.stackrestore
 // WIN32: }
 
 // Now test both.
@@ -81,8 +95,7 @@
   return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
 }
 
-// WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
-// WIN32:   %[[arg1:.*]] = alloca %struct.A, align 4
+// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
 // WIN32:   alloca i1
 // WIN32:   %[[arg1_cond:.*]] = alloca i1
 //        Start all four cleanups as deactivated.
@@ -92,10 +105,10 @@
 // WIN32:   store i1 false
 // WIN32:   br i1
 //        True condition.
-// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   store i1 true
 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   store i1 true, i1* %[[arg1_cond]]
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   store i1 true
@@ -108,13 +121,13 @@
 // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
 //        Two normal cleanups for TakeRef args.
 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32:   ret i32
 //
 //        Somewhere in the landing pad soup, we conditionally destroy arg1.
 // WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
 // WIN32:   br i1 %[[isactive]]
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32: }
 
 namespace crash_on_partial_destroy {
diff --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index bff5647..9800137 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -47,6 +47,14 @@
   int a, b, c, d, e, f;
 };
 
+// WIN32: declare void @"{{.*take_bools_and_chars.*}}"
+// WIN32:       (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
+// WIN32:           i8, [3 x i8], i8, [3 x i8], i32, i8 }>* inalloca)
+void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
+void call_bools_and_chars() {
+  take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
+}
+
 // Returning structs that fit into a register.
 Small small_return() { return Small(); }
 // LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
@@ -103,11 +111,11 @@
 
 // Test that dtors are invoked in the callee.
 void small_arg_with_dtor(SmallWithDtor s) {}
-// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval align 4 %s) {{.*}} {
-// WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"(%struct.SmallWithDtor* %s)
+// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
+// WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
 // WIN32: }
-// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval %s) {{.*}} {
-// WIN64:   call void @"\01??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
+// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WIN64:   call void @"\01??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 
 // Test that references aren't destroyed in the callee.
@@ -141,13 +149,13 @@
 
 void small_arg_with_vftable(SmallWithVftable s) {}
 // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
-// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval align 4 %s)
-// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval %s)
+// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
+// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
 
 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
 // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
-// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval align 4 %s)
-// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval %s)
+// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
+// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
 
 void big_arg(Big s) {}
 // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
@@ -215,8 +223,8 @@
 };
 void g(X) {
 }
-// WIN32: define void @"\01?g@@YAXUX@@@Z"(%struct.X* byval align 4) {{.*}} {
-// WIN32:   call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* %0)
+// WIN32: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X }>* inalloca) {{.*}} {
+// WIN32:   call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
 // WIN32: }
 void f() {
   g(X());
@@ -224,3 +232,34 @@
 // WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
 // WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
 // WIN32: }
+
+
+namespace test2 {
+// We used to crash on this due to the mixture of POD byval and non-trivial
+// byval.
+
+struct NonTrivial {
+  NonTrivial();
+  NonTrivial(const NonTrivial &o);
+  ~NonTrivial();
+  int a;
+};
+struct POD { int b; };
+
+int foo(NonTrivial a, POD b);
+void bar() {
+  POD b;
+  b.b = 13;
+  int c = foo(NonTrivial(), b);
+}
+// WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} {
+// WIN32:   %[[argmem:[^ ]*]] = alloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]], inalloca
+// WIN32:   getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// WIN32:   call void @llvm.memcpy
+// WIN32:   getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
+// WIN32:   call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
+// WIN32:   call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
+// WIN32:   ret void
+// WIN32: }
+
+}
diff --git a/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
index 3e01f03..0b01b27 100644
--- a/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
+++ b/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
@@ -10,11 +10,11 @@
 // Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d.
 //
 // CHECK-LABEL: define void @"\01?test_arc_order@@YAXUA@@PAAAPAUobjc_object@@01@Z"
-// CHECK:                       ({{.*}} %[[a:.*]], {{.*}}, {{.*}} %[[c:.*]], {{.*}})
+// CHECK:                       (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca)
 void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
-  // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]])
+  // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
   // CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
-  // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]])
+  // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %{{.*}})
   // CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
   // CHECK: ret void
 }