Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -847,9 +847,17 @@ getCXXABI().useThunkForDtorVariant(cast(D), GD.getDtorType())) { // Destructor variants in the Microsoft C++ ABI are always internal or - // linkonce_odr thunks emitted on an as-needed basis. - return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage - : llvm::GlobalValue::LinkOnceODRLinkage; + // linkonce_odr thunks emitted on an as-needed basis. Except destructors + // that have a virtual base and dllimport attributes. Those will + // be marked with an external linkage. + if (cast(D)->getParent()->getNumVBases() && + (GD.getDtorType() == CXXDtorType::Dtor_Complete || + GD.getDtorType() == CXXDtorType::Dtor_Base) && + D->hasAttr()) + return llvm::Function::AvailableExternallyLinkage; + else + return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage + : llvm::GlobalValue::LinkOnceODRLinkage; } if (isa(D) && Index: test/CodeGenCXX/dllimport-dtor-thunks.cpp =================================================================== --- test/CodeGenCXX/dllimport-dtor-thunks.cpp +++ test/CodeGenCXX/dllimport-dtor-thunks.cpp @@ -23,9 +23,7 @@ virtual ~ImportOverrideVDtor() {} }; -// Virtually inherits from a non-dllimport base class. This time we need to call -// the complete destructor and emit it inline. It's not exported from the DLL, -// and it must be emitted. +// Virtually inherits from a non-dllimport base class. Emit the virtual base destructor. struct __declspec(dllimport) ImportVBaseOverrideVDtor : public virtual BaseClass { virtual ~ImportVBaseOverrideVDtor() {} @@ -44,6 +42,6 @@ // CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}}) // CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}}) -// CHECK-LABEL: define linkonce_odr void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" +// CHECK-LABEL: declare dllimport void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" // CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ" // CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ" Index: test/CodeGenCXX/dllimport-virtual-base.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/dllimport-virtual-base.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple i386-pc-windows -emit-llvm -fms-compatibility %s -x c++ -o - | FileCheck %s + +namespace test1 { +struct BaseClass { + ~BaseClass(); +}; + +struct __declspec(dllimport) Concrete : virtual BaseClass { +}; + +Concrete c; +} // namespace test1 + +namespace test2 { +class BaseClass { +public: + virtual ~BaseClass(){}; +}; + +class __declspec(dllimport) VirtualClass : public virtual BaseClass { +public: + virtual ~VirtualClass(){}; +}; + +int main() { + VirtualClass c; + return 0; +} +} // namespace test2 + +namespace test3 { +class IVirtualBase { +public: + virtual ~IVirtualBase(){}; + virtual void speak() = 0; +}; + +class VirtualClass : public virtual IVirtualBase { +public: + virtual ~VirtualClass(){}; + virtual void eat() = 0; +}; + +class __declspec(dllimport) ConcreteClass : public VirtualClass { +public: + ConcreteClass(int nn); + void speak(); + void eat(); + virtual ~ConcreteClass(); + +private: + int n; +}; + +int main() { + ConcreteClass c(10); + c.speak(); + c.eat(); + return 0; +} +} // namespace test3 + +// CHECK-LABEL: declare dllimport x86_thiscallcc %"struct.test1::Concrete"* @"\01??0Concrete@test1@@QAE@XZ" +// CHECK-LABEL: declare dllimport x86_thiscallcc %"class.test2::VirtualClass"* @"\01??0VirtualClass@test2@@QAE@XZ" +// CHECK-LABEL: declare dllimport x86_thiscallcc %"class.test3::ConcreteClass"* @"\01??0ConcreteClass@test3@@QAE@H@Z" +// CHECK-NOT: ??_DConcrete@test1@@QEAAXXZ +// CHECK-NOT: ??_DVirtualClass@test2@@QEAAXXZ +// CHECK-NOT: ??_DConcreteClass@test3@@QEAAXXZ