Index: cfe/trunk/lib/CodeGen/CGVTables.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGVTables.cpp +++ cfe/trunk/lib/CodeGen/CGVTables.cpp @@ -677,7 +677,8 @@ // We're at the end of the translation unit, so the current key // function is fully correct. - if (const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD)) { + const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD); + if (keyFunction && !RD->hasAttr()) { // If this class has a key function, use that to determine the // linkage of the vtable. const FunctionDecl *def = nullptr; Index: cfe/trunk/test/CodeGenCXX/dllimport.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/dllimport.cpp +++ cfe/trunk/test/CodeGenCXX/dllimport.cpp @@ -672,6 +672,18 @@ // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 0 } +namespace PR21355 { + struct __declspec(dllimport) S { + virtual ~S(); + }; + S::~S() {} + + // S::~S is a key function, so we would ordinarily emit a strong definition for + // the vtable. However, S is imported, so the vtable should be too. + + // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant [4 x i8*] +} + // MS ignores DLL attributes on partial specializations. template struct PartiallySpecializedClassTemplate {}; template struct __declspec(dllimport) PartiallySpecializedClassTemplate { void f() {} };