Fix marking of virtual members for nested classes whose first non-pure virtual function has a body inlined in the class

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92855 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index c04a8fa..d2ba77d 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -1490,52 +1490,8 @@
       return;
   }
 
-  llvm::GlobalVariable::LinkageTypes Linkage =
-    llvm::GlobalVariable::InternalLinkage;
-  if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
-    Linkage = llvm::GlobalVariable::InternalLinkage;
-  else if (KeyFunction && !MD->isInlined()) {
-    switch (MD->getTemplateSpecializationKind()) {
-    case TSK_Undeclared:
-    case TSK_ExplicitSpecialization:
-      Linkage = llvm::GlobalVariable::ExternalLinkage;
-      break;
-
-    case TSK_ImplicitInstantiation:
-    case TSK_ExplicitInstantiationDefinition:
-      Linkage = llvm::GlobalVariable::WeakODRLinkage;
-      break;
-
-    case TSK_ExplicitInstantiationDeclaration:
-      // FIXME: Use available_externally linkage. However, this currently
-      // breaks LLVM's build due to undefined symbols.
-      //      Linkage = llvm::GlobalVariable::AvailableExternallyLinkage;
-      Linkage = llvm::GlobalVariable::WeakODRLinkage;
-      break;
-    }
-  }
-  else if (KeyFunction)
-    Linkage = llvm::GlobalVariable::WeakODRLinkage;
-  else {
-    Linkage = llvm::GlobalVariable::WeakODRLinkage;
-    
-    switch (RD->getTemplateSpecializationKind()) {
-    case TSK_Undeclared:
-    case TSK_ExplicitSpecialization:
-    case TSK_ImplicitInstantiation:
-    case TSK_ExplicitInstantiationDefinition:
-      break;
-
-    case TSK_ExplicitInstantiationDeclaration:
-      // FIXME: Use available_externally linkage. However, this currently
-      // breaks LLVM's build due to undefined symbols.
-      // Linkage = llvm::GlobalVariable::AvailableExternallyLinkage;
-      break;
-    }
-  }
-  
   // Emit the data.
-  GenerateClassData(Linkage, RD);
+  GenerateClassData(CGM.getVtableLinkage(RD), RD);
 
   for (CXXRecordDecl::method_iterator i = RD->method_begin(),
        e = RD->method_end(); i != e; ++i) {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 85d57e7..e0e8c54 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -887,6 +887,60 @@
   EmitGlobalVarDefinition(D);
 }
 
+llvm::GlobalVariable::LinkageTypes 
+CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) {
+  // Get the key function.
+  const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD);
+  
+  if (KeyFunction) {
+    const FunctionDecl *Def = 0;
+    if (KeyFunction->getBody(Def))
+      KeyFunction = cast<CXXMethodDecl>(Def);
+  }
+  
+  if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
+    return llvm::GlobalVariable::InternalLinkage;
+  else if (KeyFunction) {
+    switch (KeyFunction->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ExplicitSpecialization:
+        if (KeyFunction->isInlined())
+          return llvm::GlobalVariable::WeakODRLinkage;
+        
+        return llvm::GlobalVariable::ExternalLinkage;
+        
+      case TSK_ImplicitInstantiation:
+      case TSK_ExplicitInstantiationDefinition:
+        return llvm::GlobalVariable::WeakODRLinkage;
+        
+      case TSK_ExplicitInstantiationDeclaration:
+        // FIXME: Use available_externally linkage. However, this currently
+        // breaks LLVM's build due to undefined symbols.
+        //      return llvm::GlobalVariable::AvailableExternallyLinkage;
+        return llvm::GlobalVariable::WeakODRLinkage;
+    }
+  } else if (KeyFunction) {
+    return llvm::GlobalVariable::WeakODRLinkage;
+  } else {
+    switch (RD->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ExplicitSpecialization:
+      case TSK_ImplicitInstantiation:
+      case TSK_ExplicitInstantiationDefinition:
+        return llvm::GlobalVariable::WeakODRLinkage;
+        
+      case TSK_ExplicitInstantiationDeclaration:
+        // FIXME: Use available_externally linkage. However, this currently
+        // breaks LLVM's build due to undefined symbols.
+        //   return llvm::GlobalVariable::AvailableExternallyLinkage;
+        return llvm::GlobalVariable::WeakODRLinkage;
+    }
+  }
+  
+  // Silence GCC warning.
+  return llvm::GlobalVariable::WeakODRLinkage;
+}
+
 static CodeGenModule::GVALinkage
 GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
   // Everything located semantically within an anonymous namespace is
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index a31e23b..575b518 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -407,6 +407,10 @@
     GVA_TemplateInstantiation
   };
 
+  /// getVtableLinkage - Return the appropriate linkage for the vtable, VTT,
+  /// and type information of the given class.
+  llvm::GlobalVariable::LinkageTypes getVtableLinkage(const CXXRecordDecl *RD);
+  
 private:
   /// UniqueMangledName - Unique a name by (if necessary) inserting it into the
   /// MangledNames string map.