1*55efb68cSReid Kleckner // RUN: %clang_cc1 -std=c++17 -verify -Wno-defaulted-function-deleted %s -triple x86_64-windows-msvc
2*55efb68cSReid Kleckner 
3*55efb68cSReid Kleckner // MSVC emits the complete destructor as if it were its own special member.
4*55efb68cSReid Kleckner // Clang attempts to do the same. This affects the diagnostics clang emits,
5*55efb68cSReid Kleckner // because deleting a type with a user declared constructor implicitly
6*55efb68cSReid Kleckner // references the destructors of virtual bases, which might be deleted or access
7*55efb68cSReid Kleckner // controlled.
8*55efb68cSReid Kleckner 
9*55efb68cSReid Kleckner namespace t1 {
10*55efb68cSReid Kleckner struct A {
11*55efb68cSReid Kleckner   ~A() = delete; // expected-note {{deleted here}}
12*55efb68cSReid Kleckner };
13*55efb68cSReid Kleckner struct B {
14*55efb68cSReid Kleckner   B() = default;
15*55efb68cSReid Kleckner   A o; // expected-note {{destructor of 'B' is implicitly deleted because field 'o' has a deleted destructor}}
16*55efb68cSReid Kleckner };
17*55efb68cSReid Kleckner struct C : virtual B {
18*55efb68cSReid Kleckner   ~C(); // expected-error {{attempt to use a deleted function}}
19*55efb68cSReid Kleckner };
delete1(C * p)20*55efb68cSReid Kleckner void delete1(C *p) { delete p; } // expected-note {{in implicit destructor for 't1::C' first required here}}
delete2(C * p)21*55efb68cSReid Kleckner void delete2(C *p) { delete p; }
22*55efb68cSReid Kleckner }
23*55efb68cSReid Kleckner 
24*55efb68cSReid Kleckner namespace t2 {
25*55efb68cSReid Kleckner struct A {
26*55efb68cSReid Kleckner private:
27*55efb68cSReid Kleckner   ~A();
28*55efb68cSReid Kleckner };
29*55efb68cSReid Kleckner struct B {
30*55efb68cSReid Kleckner   B() = default;
31*55efb68cSReid Kleckner   A o; // expected-note {{destructor of 'B' is implicitly deleted because field 'o' has an inaccessible destructor}}
32*55efb68cSReid Kleckner };
33*55efb68cSReid Kleckner struct C : virtual B {
34*55efb68cSReid Kleckner   ~C(); // expected-error {{attempt to use a deleted function}}
35*55efb68cSReid Kleckner };
useCompleteDtor(C * p)36*55efb68cSReid Kleckner void useCompleteDtor(C *p) { delete p; } // expected-note {{in implicit destructor for 't2::C' first required here}}
37*55efb68cSReid Kleckner }
38*55efb68cSReid Kleckner 
39*55efb68cSReid Kleckner namespace t3 {
40*55efb68cSReid Kleckner template <unsigned N>
41*55efb68cSReid Kleckner class Base { ~Base(); }; // expected-note 1{{declared private here}}
42*55efb68cSReid Kleckner // No diagnostic.
43*55efb68cSReid Kleckner class Derived0 : virtual Base<0> { ~Derived0(); };
44*55efb68cSReid Kleckner class Derived1 : virtual Base<1> {};
45*55efb68cSReid Kleckner // Emitting complete dtor causes a diagnostic.
46*55efb68cSReid Kleckner struct Derived2 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}}
47*55efb68cSReid Kleckner                   virtual Base<2> {
48*55efb68cSReid Kleckner   ~Derived2();
49*55efb68cSReid Kleckner };
useCompleteDtor(Derived2 * p)50*55efb68cSReid Kleckner void useCompleteDtor(Derived2 *p) { delete p; } // expected-note {{in implicit destructor for 't3::Derived2' first required here}}
51*55efb68cSReid Kleckner }
52