[cfe-commits] r92855 - in /cfe/trunk: lib/CodeGen/CGVtable.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/virtual-member-functions.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 6 12:27:16 PST 2010


Author: dgregor
Date: Wed Jan  6 14:27:16 2010
New Revision: 92855

URL: http://llvm.org/viewvc/llvm-project?rev=92855&view=rev
Log:
Fix marking of virtual members for nested classes whose first non-pure virtual function has a body inlined in the class

Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp

Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=92855&r1=92854&r2=92855&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Wed Jan  6 14:27:16 2010
@@ -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) {

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=92855&r1=92854&r2=92855&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Jan  6 14:27:16 2010
@@ -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

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=92855&r1=92854&r2=92855&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Wed Jan  6 14:27:16 2010
@@ -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.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=92855&r1=92854&r2=92855&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jan  6 14:27:16 2010
@@ -5693,14 +5693,40 @@
   if (!RD->isDynamicClass())
     return;
 
-  // Only out-of-line definitions matter.
-  if (!MD->isOutOfLine())
+  // Ignore declarations that are not definitions.
+  if (!MD->isThisDeclarationADefinition())
     return;
   
-  const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
-  if (!KeyFunction || KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
+  if (isa<CXXConstructorDecl>(MD)) {
+    switch (MD->getParent()->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      // Classes that aren't instantiations of templates don't need their
+      // virtual methods marked until we see the definition of the key 
+      // function.
+      return;
+        
+    case TSK_ImplicitInstantiation:
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      // This is a constructor of a class template; mark all of the virtual
+      // members as referenced to ensure that they get instantiatied.
+      break;
+    }
+  } else if (!MD->isOutOfLine()) {
+    // Consider only out-of-line definitions of member functions. When we see
+    // an inline definition, it's too early to compute the key function.
     return;
-
+  } else if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD)) {
+    // If this is not the key function, we don't need to mark virtual members.
+    if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
+      return;
+  } else {
+    // The class has no key function, so we've already noted that we need to
+    // mark the virtual members of this class.
+    return;
+  }
+  
   // We will need to mark all of the virtual members as referenced to build the
   // vtable.
   ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));

Modified: cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp?rev=92855&r1=92854&r2=92855&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp (original)
+++ cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp Wed Jan  6 14:27:16 2010
@@ -41,3 +41,15 @@
 
 template struct Derived<int>; // expected-note{{instantiation}}
 
+template<typename T>
+struct HasOutOfLineKey {
+  HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}}
+  virtual T *f(float *fp);
+};
+
+template<typename T>
+T *HasOutOfLineKey<T>::f(float *fp) {
+  return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
+}
+
+HasOutOfLineKey<int> out_of_line;





More information about the cfe-commits mailing list