Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -2601,7 +2601,15 @@ // is always '6' for vftables. msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); - if (Derived->hasAttr()) + bool NeedLocalVFT = false; + if (Derived->hasAttr()) { + // Only dllimported classes with virtual d-tor may need local vtbl + // for proper memory deallocation without crossing DLL boundaries. + if (const CXXDestructorDecl *Destructor = Derived->getDestructor()) + if (Destructor->isVirtual()) + NeedLocalVFT = true; + } + if (NeedLocalVFT) Mangler.getStream() << "\01??_S"; else Mangler.getStream() << "\01??_7"; Index: test/CodeGenCXX/PR26569.cpp =================================================================== --- test/CodeGenCXX/PR26569.cpp +++ test/CodeGenCXX/PR26569.cpp @@ -4,17 +4,17 @@ virtual void m_fn1(); }; template -class B : virtual A {}; +class B : public virtual A {}; extern template class __declspec(dllimport) B; class __declspec(dllexport) C : B {}; // CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] -// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_S?$B@H@@6B@") +// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7?$B@H@@6B@") // CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7A@@6B@") // CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_C]], i32 0, i32 1) -// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_B]], i32 0, i32 1) +// CHECK-DAG: @"\01??_7?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_B]], i32 0, i32 1) // CHECK-DAG: @"\01??_7A@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_A]], i32 0, i32 1) // CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] Index: test/CodeGenCXX/dllimport-rtti.cpp =================================================================== --- test/CodeGenCXX/dllimport-rtti.cpp +++ test/CodeGenCXX/dllimport-rtti.cpp @@ -4,8 +4,8 @@ struct __declspec(dllimport) S { virtual void f() {} } s; -// MSVC: [[VF_S:.*]] = private unnamed_addr constant [2 x i8*] -// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VF_S]], i32 0, i32 1) +// MSVC: [[VF_7:.*]] = private unnamed_addr constant [2 x i8*] +// MSVC-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VF_7]], i32 0, i32 1) // MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr // MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr // MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr Index: test/CodeGenCXX/dllimport.cpp =================================================================== --- test/CodeGenCXX/dllimport.cpp +++ test/CodeGenCXX/dllimport.cpp @@ -620,9 +620,18 @@ struct __declspec(dllimport) W { virtual void foo() {} }; USECLASS(W) // vftable: -// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] +// MO1-DAG: @"\01??_7W@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] // GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] +struct __declspec(dllimport) W2 { + virtual ~W2(); + virtual void foo() {} +}; +USECLASS(W2) +// vftable: +// MO1-DAG: @"\01??_SW2@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GO1-DAG: @_ZTV2W2 = external dllimport unnamed_addr constant [5 x i8*] + struct __declspec(dllimport) KeyFuncClass { constexpr KeyFuncClass() {} virtual void foo();