1 // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++11 -triple %itanium_abi_triple -fsyntax-only %s 2 // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++11 -triple %ms_abi_triple -verify %s 3 4 namespace Test1 { 5 6 // Should be accepted under the Itanium ABI (first RUN line) but rejected 7 // under the Microsoft ABI (second RUN line), as Microsoft ABI requires 8 // operator delete() lookups to be done when vtables are marked used. 9 10 struct A { 11 void operator delete(void *); // expected-note {{member found by ambiguous name lookup}} 12 }; 13 14 struct B { 15 void operator delete(void *); // expected-note {{member found by ambiguous name lookup}} 16 }; 17 18 struct C : A, B { 19 ~C(); 20 }; 21 22 struct VC : A, B { 23 virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}} 24 }; 25 26 void f() { 27 // This marks VC's vtable used. 28 VC vc; 29 } 30 31 } 32 33 namespace Test2 { 34 35 // In the MSVC ABI, functions must destroy their aggregate arguments. foo 36 // requires a dtor for B, but we can't implicitly define it because ~A is 37 // private. bar should be able to call A's private dtor without error, even 38 // though MSVC rejects bar. 39 class A { 40 private: 41 ~A(); 42 int a; 43 }; 44 45 struct B : public A { // expected-note {{destructor of 'B' is implicitly deleted because base class 'Test2::A' has an inaccessible destructor}} 46 int b; 47 }; 48 49 struct C { 50 ~C(); 51 int c; 52 }; 53 54 struct D { 55 // D has a non-trivial implicit dtor that destroys C. 56 C o; 57 }; 58 59 void foo(B b) { } // expected-error {{attempt to use a deleted function}} 60 void bar(A a) { } // no error; MSVC rejects this, but we skip the direct access check. 61 void baz(D d) { } // no error 62 63 } 64 65 #ifdef MSVC_ABI 66 namespace Test3 { 67 68 class A { 69 A(); 70 ~A(); // expected-note {{implicitly declared private here}} 71 friend void bar(A); 72 int a; 73 }; 74 75 void bar(A a) { } 76 void baz(A a) { } // no error; MSVC rejects this, but the standard allows it. 77 78 // MSVC accepts foo() but we reject it for consistency with Itanium. MSVC also 79 // rejects this if A has a copy ctor or if we call A's ctor. 80 void foo(A *a) { 81 bar(*a); // expected-error {{temporary of type 'Test3::A' has private destructor}} 82 } 83 } 84 #endif 85 86 namespace Test4 { 87 // Don't try to access the dtor of an incomplete on a function declaration. 88 class A; 89 void foo(A a); 90 } 91 92 #ifdef MSVC_ABI 93 namespace Test5 { 94 // Do the operator delete access control check from the context of the dtor. 95 class A { 96 protected: 97 void operator delete(void *); 98 }; 99 class B : public A { 100 virtual ~B(); 101 }; 102 B *test() { 103 // Previously, marking the vtable used here would do the operator delete 104 // lookup from this context, which doesn't have access. 105 return new B; 106 } 107 } 108 #endif 109 110 namespace Test6 { 111 class A { 112 protected: 113 void operator delete(void *); 114 }; 115 class B : public A { 116 virtual ~B(); 117 public: 118 virtual void m_fn1(); 119 }; 120 void fn1(B *b) { b->m_fn1(); } 121 } 122 123 namespace Test7 { 124 class A { 125 protected: 126 void operator delete(void *); 127 }; 128 struct B : public A { 129 virtual ~B(); 130 }; 131 void fn1(B b) {} 132 } 133