// the deleting destructor is emitted with the vtable, not with the
// destructor definition as in the Itanium ABI.
// If it has a definition, we do the check at that point instead.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- Class->hasUserDeclaredDestructor() &&
- !Class->getDestructor()->isDefined() &&
- !Class->getDestructor()->isDeleted()) {
- CXXDestructorDecl *DD = Class->getDestructor();
- ContextRAII SavedContext(*this, DD);
- CheckDestructor(DD);
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (Class->hasUserDeclaredDestructor() &&
+ !Class->getDestructor()->isDefined() &&
+ !Class->getDestructor()->isDeleted()) {
+ CXXDestructorDecl *DD = Class->getDestructor();
+ ContextRAII SavedContext(*this, DD);
+ CheckDestructor(DD);
+ } else if (Class->hasAttr<DLLImportAttr>()) {
+ // We always synthesize vtables on the import side. To make sure
+ // CheckDestructor gets called, mark the destructor referenced.
+ assert(Class->getDestructor() &&
+ "The destructor has always been declared on a dllimport class");
+ MarkFunctionReferenced(Loc, Class->getDestructor());
+ }
}
}
inline void S::outOfClassInlineMethod() {}
}
+namespace PR27319 {
+ // Make sure we don't assert due to not having checked for operator delete on
+ // the destructor.
+ template <typename> struct A {
+ virtual ~A() = default;
+ };
+ extern template struct __declspec(dllimport) A<int>;
+ void f() { new A<int>(); }
+ // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*]
+}
+
// MS ignores DLL attributes on partial specializations.
template <typename T> struct PartiallySpecializedClassTemplate {};
template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f(); };