llvm-project/clang/test/SemaCXX/ms-implicit-complete-dtor.cpp
Reid Kleckner 55efb68c19 [MS] Mark vbase dtors used when marking dtor used
In the MS C++ ABI, the complete destructor variant for a class with
virtual bases is emitted whereever it is needed, instead of directly
alongside the base destructor variant. The complete destructor calls the
base destructor of the current class and the base destructors of each
virtual base. In order for this to work reliably, translation units that
use the destructor of a class also need to mark destructors of virtual
bases of that class used.

Fixes PR38521

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D77081
2020-04-09 14:19:36 -07:00

52 lines
1.8 KiB
C++

// RUN: %clang_cc1 -std=c++17 -verify -Wno-defaulted-function-deleted %s -triple x86_64-windows-msvc
// MSVC emits the complete destructor as if it were its own special member.
// Clang attempts to do the same. This affects the diagnostics clang emits,
// because deleting a type with a user declared constructor implicitly
// references the destructors of virtual bases, which might be deleted or access
// controlled.
namespace t1 {
struct A {
~A() = delete; // expected-note {{deleted here}}
};
struct B {
B() = default;
A o; // expected-note {{destructor of 'B' is implicitly deleted because field 'o' has a deleted destructor}}
};
struct C : virtual B {
~C(); // expected-error {{attempt to use a deleted function}}
};
void delete1(C *p) { delete p; } // expected-note {{in implicit destructor for 't1::C' first required here}}
void delete2(C *p) { delete p; }
}
namespace t2 {
struct A {
private:
~A();
};
struct B {
B() = default;
A o; // expected-note {{destructor of 'B' is implicitly deleted because field 'o' has an inaccessible destructor}}
};
struct C : virtual B {
~C(); // expected-error {{attempt to use a deleted function}}
};
void useCompleteDtor(C *p) { delete p; } // expected-note {{in implicit destructor for 't2::C' first required here}}
}
namespace t3 {
template <unsigned N>
class Base { ~Base(); }; // expected-note 1{{declared private here}}
// No diagnostic.
class Derived0 : virtual Base<0> { ~Derived0(); };
class Derived1 : virtual Base<1> {};
// Emitting complete dtor causes a diagnostic.
struct Derived2 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}}
virtual Base<2> {
~Derived2();
};
void useCompleteDtor(Derived2 *p) { delete p; } // expected-note {{in implicit destructor for 't3::Derived2' first required here}}
}