Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -3155,18 +3155,6 @@ /// should have for the given type. static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) { - // Itanium C++ ABI 2.9.5p7: - // In addition, it and all of the intermediate abi::__pointer_type_info - // structs in the chain down to the abi::__class_type_info for the - // incomplete class type must be prevented from resolving to the - // corresponding type_info structs for the complete class type, possibly - // by making them local static objects. Finally, a dummy class RTTI is - // generated for the incomplete type that will not resolve to the final - // complete class RTTI (because the latter need not exist), possibly by - // making it a local static object. - if (ContainsIncompleteClassType(Ty)) - return llvm::GlobalValue::InternalLinkage; - switch (Ty->getLinkage()) { case NoLinkage: case InternalLinkage: @@ -3184,6 +3172,11 @@ if (const RecordType *Record = dyn_cast(Ty)) { const CXXRecordDecl *RD = cast(Record->getDecl()); + // If the class is incomplete, we're forming the pointee of an incomplete + // pointer typeinfo. This linkage will only be used for the type name; + // give it linkonce_odr linkage. + if (!RD->isCompleteDefinition()) + return llvm::GlobalValue::LinkOnceODRLinkage; if (RD->hasAttr()) return llvm::GlobalValue::WeakODRLinkage; if (CGM.getTriple().isWindowsItaniumEnvironment()) @@ -3255,20 +3248,20 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( QualType Ty, - llvm::GlobalVariable::LinkageTypes Linkage, - llvm::GlobalValue::VisibilityTypes Visibility, + llvm::GlobalVariable::LinkageTypes TypeNameLinkage, + llvm::GlobalValue::VisibilityTypes TypeNameVisibility, llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) { // Add the vtable pointer. BuildVTablePointer(cast(Ty)); // And the name. - llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); + llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, TypeNameLinkage); llvm::Constant *TypeNameField; // If we're supposed to demote the visibility, be sure to set a flag // to use a string comparison for type_info comparisons. ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness = - CXXABI.classifyRTTIUniqueness(Ty, Linkage); + CXXABI.classifyRTTIUniqueness(Ty, TypeNameLinkage); if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) { // The flag is the sign bit, which on ARM64 is defined to be clear // for global pointers. This is very ARM64-specific. @@ -3371,6 +3364,28 @@ llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); + // Itanium C++ ABI 2.9.5p7: + // In addition, it and all of the intermediate abi::__pointer_type_info + // structs in the chain down to the abi::__class_type_info for the + // incomplete class type must be prevented from resolving to the + // corresponding type_info structs for the complete class type, possibly + // by making them local static objects. Finally, a dummy class RTTI is + // generated for the incomplete type that will not resolve to the final + // complete class RTTI (because the latter need not exist), possibly by + // making it a local static object. + // + // Two abi::__pbase_type_info objects can always be compared for equality + // (i.e. of the types represented) or ordering by comparison of their name + // NTBS addresses. In addition, unless either or both have either of the + // incomplete flags set, equality can be tested by comparing the type_info + // addresses. + llvm::GlobalVariable::LinkageTypes TypeInfoLinkage = TypeNameLinkage; + llvm::GlobalValue::VisibilityTypes TypeInfoVisibility = TypeNameVisibility; + if (ContainsIncompleteClassType(Ty)) { + TypeInfoLinkage = llvm::GlobalVariable::InternalLinkage; + TypeInfoVisibility = llvm::GlobalValue::DefaultVisibility; + } + SmallString<256> Name; llvm::raw_svector_ostream Out(Name); CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); @@ -3378,7 +3393,7 @@ llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); llvm::GlobalVariable *GV = new llvm::GlobalVariable(M, Init->getType(), - /*Constant=*/true, Linkage, Init, Name); + /*Constant=*/true, TypeInfoLinkage, Init, Name); // If there's already an old global variable, replace it with the new one. if (OldGV) { @@ -3411,10 +3426,10 @@ // All of this is to say that it's important that both the type_info // object and the type_info name be uniqued when weakly emitted. - TypeName->setVisibility(Visibility); + TypeName->setVisibility(TypeNameVisibility); CGM.setDSOLocal(TypeName); - GV->setVisibility(Visibility); + GV->setVisibility(TypeInfoVisibility); CGM.setDSOLocal(GV); TypeName->setDLLStorageClass(DLLStorageClass); Index: test/CodeGenCXX/rtti-linkage.cpp =================================================================== --- test/CodeGenCXX/rtti-linkage.cpp +++ test/CodeGenCXX/rtti-linkage.cpp @@ -3,27 +3,36 @@ #include -// CHECK-BOTH: _ZTSP1C = internal constant -// CHECK-BOTH: _ZTS1C = internal constant +// CHECK: _ZTSP1C = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSP1C = linkonce_odr hidden constant +// CHECK: _ZTS1C = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTS1C = linkonce_odr hidden constant // CHECK-BOTH: _ZTI1C = internal constant // CHECK-BOTH: _ZTIP1C = internal constant -// CHECK-BOTH: _ZTSPP1C = internal constant +// CHECK: _ZTSPP1C = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSPP1C = linkonce_odr hidden constant // CHECK-BOTH: _ZTIPP1C = internal constant -// CHECK-BOTH: _ZTSM1Ci = internal constant +// CHECK: _ZTSM1Ci = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSM1Ci = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1Ci = internal constant -// CHECK-BOTH: _ZTSPM1Ci = internal constant +// CHECK: _ZTSPM1Ci = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSPM1Ci = linkonce_odr hidden constant // CHECK-BOTH: _ZTIPM1Ci = internal constant -// CHECK-BOTH: _ZTSM1CS_ = internal constant +// CHECK: _ZTSM1CS_ = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSM1CS_ = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1CS_ = internal constant -// CHECK-BOTH: _ZTSM1CPS_ = internal constant +// CHECK: _ZTSM1CPS_ = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSM1CPS_ = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1CPS_ = internal constant -// CHECK-BOTH: _ZTSM1A1C = internal constant +// CHECK: _ZTSM1A1C = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSM1A1C = linkonce_odr hidden constant // CHECK: _ZTS1A = linkonce_odr constant // CHECK-WITH-HIDDEN: _ZTS1A = linkonce_odr hidden constant // CHECK: _ZTI1A = linkonce_odr constant // CHECK-WITH-HIDDEN: _ZTI1A = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1A1C = internal constant -// CHECK-BOTH: _ZTSM1AP1C = internal constant +// CHECK: _ZTSM1AP1C = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTSM1AP1C = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1AP1C = internal constant // CHECK-WITH-HIDDEN: _ZTSFN12_GLOBAL__N_11DEvE = internal constant