diff options
Diffstat (limited to 'lib/CodeGen/CGRTTI.cpp')
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 100f73377d..c358c48e80 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -484,6 +484,58 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { Fields.push_back(VTable); } +// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures +// from available_externally to the correct linkage if necessary. An example of +// this is: +// +// struct A { +// virtual void f(); +// }; +// +// const std::type_info &g() { +// return typeid(A); +// } +// +// void A::f() { } +// +// When we're generating the typeid(A) expression, we do not yet know that +// A's key function is defined in this translation unit, so we will give the +// typeinfo and typename structures available_externally linkage. When A::f +// forces the vtable to be generated, we need to change the linkage of the +// typeinfo and typename structs, otherwise we'll end up with undefined +// externals when linking. +static void +maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV, + QualType Ty) { + // We're only interested in globals with available_externally linkage. + if (!GV->hasAvailableExternallyLinkage()) + return; + + // Get the real linkage for the type. + llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty); + + // If variable is supposed to have available_externally linkage, we don't + // need to do anything. + if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) + return; + + // Update the typeinfo linkage. + GV->setLinkage(Linkage); + + // Get the typename global. + llvm::SmallString<256> OutName; + CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, OutName); + llvm::StringRef Name = OutName.str(); + + llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name); + + assert(TypeNameGV->hasAvailableExternallyLinkage() && + "Type name has different linkage from type info!"); + + // And update its linkage. + TypeNameGV->setLinkage(Linkage); +} + llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // We want to operate on the canonical type. Ty = CGM.getContext().getCanonicalType(Ty); @@ -494,8 +546,11 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { llvm::StringRef Name = OutName.str(); llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); - if (OldGV && !OldGV->isDeclaration()) + if (OldGV && !OldGV->isDeclaration()) { + maybeUpdateRTTILinkage(CGM, OldGV, Ty); + return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); + } // Check if there is already an external RTTI descriptor for this type. bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); |