Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -3800,6 +3800,12 @@ static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor, StructorType dtorType) { + // If the class has dllimport attribute and has a virual base, the destructor + // is equivalent to the virtual base destrutor. + if (dtor->getParent()->getNumVBases() && dtor->hasAttr() && + (dtorType == StructorType::Complete || dtorType == StructorType::Base) && + CGM.TryEmitBaseDestructorAsAlias(dtor)) + return; // The complete destructor is equivalent to the base destructor for // classes with no virtual bases, so try to emit it as an alias. if (!dtor->getParent()->getNumVBases() && Index: test/CodeGenCXX/dllimport-base.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/dllimport-base.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple i386-pc-windows -emit-llvm -fms-compatibility %s -x c++ -o - | FileCheck %s + +// CHECK: declare dllimport x86_thiscallcc void @"\01??1VirtualClass@test1@@UAE@XZ" +// CHECK: declare dllimport x86_thiscallcc void @"\01??1VirtualClass@test2@@UAE@XZ" +// CHECK-NOT: ??_DVirtualClass@@QEAAXXZ + +namespace test1 { +struct __declspec(dllimport) VirtualClass { +public: + virtual ~VirtualClass(){}; +}; + +int main() { + VirtualClass c; + return 0; +} +} // namespace test1 + +namespace test2 { +class BaseClass { +public: + virtual ~BaseClass(){}; +}; + +class __declspec(dllimport) VirtualClass : public BaseClass { +public: + virtual ~VirtualClass(){}; +}; + +int main() { + VirtualClass c; + return 0; +} +} // namespace test2 + +namespace test3 { +class BaseClass { +public: + virtual ~BaseClass(){}; +}; + +class __declspec(dllimport) VirtualClass : public virtual BaseClass { +public: + virtual ~VirtualClass(){}; +}; + +int main() { + VirtualClass c; + return 0; +} +} // namespace test3 Index: test/CodeGenCXX/dllimport-dtor-thunks.cpp =================================================================== --- test/CodeGenCXX/dllimport-dtor-thunks.cpp +++ test/CodeGenCXX/dllimport-dtor-thunks.cpp @@ -44,6 +44,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,67 @@ +// 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: ??_DVirtualClass@@QEAAXXZ +// CHECK-NOT: ??_DConcreteClass@@QEAAXXZ