[ms-cxxabi] Destroy temporary record arguments in the callee
Itanium destroys them in the caller at the end of the full expression,
but MSVC destroys them in the callee. This is further complicated by
the need to emit EH-only destructor cleanups in the caller.
This should help clang compile MSVC's debug iterators more correctly.
There is still an outstanding issue in PR5064 of a memcpy emitted by the
LLVM backend, which is not correct for C++ records.
Fixes PR16226.
Reviewers: rjmccall
Differential Revision: http://llvm-reviews.chandlerc.com/D929
llvm-svn: 184543
diff --git a/clang/test/SemaCXX/microsoft-dtor-lookup.cpp b/clang/test/SemaCXX/microsoft-dtor-lookup.cpp
index e7a6097..d264bab 100644
--- a/clang/test/SemaCXX/microsoft-dtor-lookup.cpp
+++ b/clang/test/SemaCXX/microsoft-dtor-lookup.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi itanium -fsyntax-only %s
-// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -verify %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -verify -DMSVC_ABI %s
+
+namespace Test1 {
// Should be accepted under the Itanium ABI (first RUN line) but rejected
// under the Microsoft ABI (second RUN line), as Microsoft ABI requires
@@ -21,3 +23,65 @@
struct VC : A, B {
virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}}
};
+
+}
+
+namespace Test2 {
+
+// In the MSVC ABI, functions must destroy their aggregate arguments. foo
+// requires a dtor for B, but we can't implicitly define it because ~A is
+// private. bar should be able to call A's private dtor without error, even
+// though MSVC rejects bar.
+
+class A {
+private:
+ ~A(); // expected-note 2{{declared private here}}
+ int a;
+};
+
+struct B : public A { // expected-error {{base class 'Test2::A' has private destructor}}
+ int b;
+};
+
+struct C {
+ ~C();
+ int c;
+};
+
+struct D {
+ // D has a non-trivial implicit dtor that destroys C.
+ C o;
+};
+
+void foo(B b) { } // expected-note {{implicit destructor for 'Test2::B' first required here}}
+void bar(A a) { } // expected-error {{variable of type 'Test2::A' has private destructor}}
+void baz(D d) { } // no error
+
+}
+
+#ifdef MSVC_ABI
+namespace Test3 {
+
+class A {
+ A();
+ ~A(); // expected-note 2{{implicitly declared private here}}
+ friend void bar(A);
+ int a;
+};
+
+void bar(A a) { }
+void baz(A a) { } // expected-error {{variable of type 'Test3::A' has private destructor}}
+
+// MSVC accepts foo() but we reject it for consistency with Itanium. MSVC also
+// rejects this if A has a copy ctor or if we call A's ctor.
+void foo(A *a) {
+ bar(*a); // expected-error {{temporary of type 'Test3::A' has private destructor}}
+}
+}
+#endif
+
+namespace Test4 {
+// Don't try to access the dtor of an incomplete on a function declaration.
+class A;
+void foo(A a);
+}