From: Hans Wennborg Date: Wed, 13 Apr 2016 20:21:15 +0000 (+0000) Subject: Make sure CheckDestructor gets called on dllimported classes if the vtable is used... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6fd58932619f63bad375655a14416729bdc354aa;p=clang Make sure CheckDestructor gets called on dllimported classes if the vtable is used (PR27319) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@266242 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 995378c073..40be8d6456 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -13314,13 +13314,20 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, // 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()) { + // 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()); + } } } diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 433628f9c2..2b159207a5 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -743,6 +743,17 @@ namespace PR21366 { inline void S::outOfClassInlineMethod() {} } +namespace PR27319 { + // Make sure we don't assert due to not having checked for operator delete on + // the destructor. + template struct A { + virtual ~A() = default; + }; + extern template struct __declspec(dllimport) A; + void f() { new A(); } + // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] +} + // MS ignores DLL attributes on partial specializations. template struct PartiallySpecializedClassTemplate {}; template struct __declspec(dllimport) PartiallySpecializedClassTemplate { void f(); };