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 Klecknervoid delete1(C *p) { delete p; } // expected-note {{in implicit destructor for 't1::C' first required here}} delete2(C * p)21*55efb68cSReid Klecknervoid 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 Klecknervoid 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 Klecknervoid useCompleteDtor(Derived2 *p) { delete p; } // expected-note {{in implicit destructor for 't3::Derived2' first required here}} 51*55efb68cSReid Kleckner } 52