Don't emit strong vtable definitions for imported classes with key functions (PR21355)
authorHans Wennborg <hans@hanshq.net>
Thu, 23 Oct 2014 22:40:46 +0000 (22:40 +0000)
committerHans Wennborg <hans@hanshq.net>
Thu, 23 Oct 2014 22:40:46 +0000 (22:40 +0000)
Clang would previously assert on the following code when targeting MinGW:

  struct __declspec(dllimport) S {
      virtual ~S();
  };
  S::~S() {}

Because ~S is a key function and the class is dllimport, we would try to emit a
strong definition of the vtable, with dllimport - which is a conflict. We
should not emit strong vtable definitions for imported classes.

Differential Revision: http://reviews.llvm.org/D5944

llvm-svn: 220532

clang/lib/CodeGen/CGVTables.cpp
clang/test/CodeGenCXX/dllimport.cpp

index a1a820a..51c29fe 100644 (file)
@@ -677,7 +677,8 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
 
   // 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<DLLImportAttr>()) {
     // If this class has a key function, use that to determine the
     // linkage of the vtable.
     const FunctionDecl *def = nullptr;
index a0703d6..d1e376b 100644 (file)
@@ -672,6 +672,18 @@ namespace PR19933 {
   // 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 <typename T> struct PartiallySpecializedClassTemplate {};
 template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f() {} };