From 2a34df32641bf80bc67cda915afbe46552cad9dc Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 6 Jan 2010 22:00:56 +0000 Subject: [PATCH] Fix linkage for RTTI names by re-using the logic for computing the linkage of vtables. Before this, we were emitting RTTI names for template instantiations with strong external linkage rather than with weak ODR linkage. llvm-svn: 92857 --- clang/lib/CodeGen/CGRTTI.cpp | 21 ++------------ clang/lib/CodeGen/CodeGenModule.cpp | 45 ++++++++++++++--------------- clang/lib/CodeGen/CodeGenModule.h | 3 +- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index 20e5fcec5684..29552ce4441c 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -360,27 +360,12 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { // If we're in an anonymous namespace, then we always want internal linkage. if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) return llvm::GlobalVariable::InternalLinkage; - + + // If this class does not have a vtable, we want weak linkage. if (!RD->isDynamicClass()) return llvm::GlobalValue::WeakODRLinkage; - // Get the key function. - const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD); - if (!KeyFunction) { - // There is no key function, the RTTI descriptor is emitted with weak_odr - // linkage. - return llvm::GlobalValue::WeakODRLinkage; - } - - // If the key function is defined, but inlined, then the RTTI descriptor is - // emitted with weak_odr linkage. - const FunctionDecl* KeyFunctionDefinition; - if (KeyFunction->getBody(KeyFunctionDefinition) && - KeyFunctionDefinition->isInlined()) - return llvm::GlobalValue::WeakODRLinkage; - - // Otherwise, the RTTI descriptor is emitted with external linkage. - return llvm::GlobalValue::ExternalLinkage; + return CodeGenModule::getVtableLinkage(RD); } case Type::Vector: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e0e8c54434e5..0dbf336dccc0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -889,18 +889,17 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { llvm::GlobalVariable::LinkageTypes CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) { - // Get the key function. - const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD); - - if (KeyFunction) { + if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) + return llvm::GlobalVariable::InternalLinkage; + + if (const CXXMethodDecl *KeyFunction + = RD->getASTContext().getKeyFunction(RD)) { + // If this class has a key function, use that to determine the linkage of + // the vtable. const FunctionDecl *Def = 0; if (KeyFunction->getBody(Def)) KeyFunction = cast(Def); - } - - if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) - return llvm::GlobalVariable::InternalLinkage; - else if (KeyFunction) { + switch (KeyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: @@ -919,22 +918,20 @@ CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) { // return llvm::GlobalVariable::AvailableExternallyLinkage; return llvm::GlobalVariable::WeakODRLinkage; } - } else if (KeyFunction) { + } + + 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; - } 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. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 575b518767e2..8f165109f5b0 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -409,7 +409,8 @@ public: /// getVtableLinkage - Return the appropriate linkage for the vtable, VTT, /// and type information of the given class. - llvm::GlobalVariable::LinkageTypes getVtableLinkage(const CXXRecordDecl *RD); + static llvm::GlobalVariable::LinkageTypes + getVtableLinkage(const CXXRecordDecl *RD); private: /// UniqueMangledName - Unique a name by (if necessary) inserting it into the