return TypeInfoIsInStandardLibrary(BuiltinTy);
}
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
-/// the given type exists somewhere else, and that we should not emit the type
-/// information in this translation unit.
-static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
- QualType Ty) {
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
// Type info for builtin types is defined in the standard library.
if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
return TypeInfoIsInStandardLibrary(BuiltinTy);
if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
return TypeInfoIsInStandardLibrary(PointerTy);
+ return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit. Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
+ QualType Ty) {
// If RTTI is disabled, don't consider key functions.
if (!Context.getLangOptions().RTTI) return false;
Fields.push_back(VTable);
}
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty,
- bool Force) {
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
// We want to operate on the canonical type.
Ty = CGM.getContext().getCanonicalType(Ty);
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
if (OldGV && !OldGV->isDeclaration())
return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy);
-
+
// Check if there is already an external RTTI descriptor for this type.
- if (!Force && ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))
+ bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+ if (!Force &&
+ (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)))
return GetAddrOfExternalRTTIDescriptor(Ty);
- llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty);
+ // Emit the standard library with external linkage.
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (IsStdLib)
+ Linkage = llvm::GlobalValue::ExternalLinkage;
+ else
+ Linkage = getTypeInfoLinkage(Ty);
// Add the vtable pointer.
BuildVTablePointer(cast<Type>(Ty));
// And the name.
Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage));
-
+
switch (Ty->getTypeClass()) {
default: assert(false && "Unhandled type class!");
OldGV->replaceAllUsesWith(NewPtr);
OldGV->eraseFromParent();
}
-
+
+ // GCC only relies on the uniqueness of the type names, not the
+ // type_infos themselves, so we can emit these as hidden symbols.
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+ CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()),
+ /*ForRTTI*/ true);
+ else if (Linkage == llvm::GlobalValue::WeakODRLinkage)
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
}
VTable->setLinkage(Linkage);
// Set the right visibility.
- CGM.setGlobalVisibility(VTable, RD);
-
- // It's okay to have multiple copies of a vtable, so don't make the
- // dynamic linker unique them. Suppress this optimization if it's
- // possible that there might be unresolved references elsewhere
- // which can only be resolved by this emission.
- if (Linkage == llvm::GlobalVariable::WeakODRLinkage &&
- VTable->getVisibility() == llvm::GlobalVariable::DefaultVisibility &&
- !RD->hasAttr<VisibilityAttr>()) {
- switch (RD->getTemplateSpecializationKind()) {
-
- // Every use of a non-template or explicitly-specialized class's
- // vtable has to emit it.
- case TSK_ExplicitSpecialization:
- case TSK_Undeclared:
- // Implicit instantiations can ignore the possibility of an
- // explicit instantiation declaration because there necessarily
- // must be an EI definition somewhere with default visibility.
- case TSK_ImplicitInstantiation:
- // If there's a key function, there may be translation units
- // that don't have the key function's definition.
- if (!CGM.Context.getKeyFunction(RD))
- // Otherwise, drop the visibility to hidden.
- VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
- break;
-
- // We have to disable the optimization if this is an EI definition
- // because there might be EI declarations in other shared objects.
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitInstantiationDeclaration:
- break;
- }
- }
+ CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false);
}
llvm::GlobalVariable *
}
}
+/// Set the symbol visibility of type information (vtable and RTTI)
+/// associated with the given type.
+void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
+ const CXXRecordDecl *RD,
+ bool IsForRTTI) const {
+ setGlobalVisibility(GV, RD);
+
+ // We want to drop the visibility to hidden for weak type symbols.
+ // This isn't possible if there might be unresolved references
+ // elsewhere that rely on this symbol being visible.
+
+ // Preconditions.
+ if (GV->getLinkage() != llvm::GlobalVariable::WeakODRLinkage ||
+ GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
+ return;
+
+ // Don't override an explicit visibility attribute.
+ if (RD->hasAttr<VisibilityAttr>())
+ return;
+
+ switch (RD->getTemplateSpecializationKind()) {
+ // We have to disable the optimization if this is an EI definition
+ // because there might be EI declarations in other shared objects.
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ return;
+
+ // Every use of a non-template or explicitly-specialized class's
+ // type information has to emit it.
+ case TSK_ExplicitSpecialization:
+ case TSK_Undeclared:
+ break;
+
+ // Implicit instantiations can ignore the possibility of an
+ // explicit instantiation declaration because there necessarily
+ // must be an EI definition somewhere with default visibility.
+ case TSK_ImplicitInstantiation:
+ break;
+ }
+
+ // If there's a key function, there may be translation units
+ // that don't have the key function's definition. But ignore
+ // this if we're emitting RTTI under -fno-rtti.
+ if (!IsForRTTI || Features.RTTI)
+ if (Context.getKeyFunction(RD))
+ return;
+
+ // Otherwise, drop the visibility to hidden.
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+}
+
llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
/// GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
+ /// setTypeVisibility - Set the visibility for the given global
+ /// value which holds information about a type.
+ void setTypeVisibility(llvm::GlobalValue *GV, const CXXRecordDecl *D,
+ bool IsForRTTI) const;
+
llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
if (isa<CXXConstructorDecl>(GD.getDecl()))
return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
// RUN: %clang_cc1 -fno-rtti -fexceptions %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// CHECK: @_ZTIN5test11AE = weak_odr constant
-// CHECK: @_ZTIN5test11BE = weak_odr constant
-// CHECK: @_ZTIN5test11CE = weak_odr constant
-// CHECK: @_ZTIN5test11DE = weak_odr constant
-// CHECK: @_ZTIPN5test11DE = weak_odr constant {{.*}} @_ZTIN5test11DE
+// CHECK: @_ZTIN5test11AE = weak_odr hidden constant
+// CHECK: @_ZTIN5test11BE = weak_odr hidden constant
+// CHECK: @_ZTIN5test11CE = weak_odr hidden constant
+// CHECK: @_ZTIN5test11DE = weak_odr hidden constant
+// CHECK: @_ZTIPN5test11DE = weak_odr hidden constant {{.*}} @_ZTIN5test11DE
// PR6974: this shouldn't crash
namespace test0 {
}
namespace test1 {
- // These classes have key functions defined out-of-line.
- // Under normal circumstances, we wouldn't generate RTTI for them;
- // under -fno-rtti, we generate RTTI only when required by EH.
+ // These classes have key functions defined out-of-line. Under
+ // normal circumstances, we wouldn't generate RTTI for them; under
+ // -fno-rtti, we generate RTTI only when required by EH. But
+ // everything gets hidden visibility because we assume that all
+ // users are also compiled under -fno-rtti and therefore will be
+ // emitting RTTI regardless of key function.
class A { virtual void foo(); };
class B { virtual void foo(); };
class C { virtual void foo(); };
__fundamental_type_info::~__fundamental_type_info() { }
}
-// CHECK: @_ZTIv = weak_odr constant
-// CHECK: @_ZTIPv = weak_odr constant
-// CHECK: @_ZTIPKv = weak_odr constant
-// CHECK: @_ZTIDi = weak_odr constant
-// CHECK: @_ZTIPDi = weak_odr constant
-// CHECK: @_ZTIPKDi = weak_odr constant
-// CHECK: @_ZTIDs = weak_odr constant
-// CHECK: @_ZTIPDs = weak_odr constant
-// CHECK: @_ZTIPKDs = weak_odr constant
-// CHECK: @_ZTIy = weak_odr constant
-// CHECK: @_ZTIPy = weak_odr constant
-// CHECK: @_ZTIPKy = weak_odr constant
-// CHECK: @_ZTIx = weak_odr constant
-// CHECK: @_ZTIPx = weak_odr constant
-// CHECK: @_ZTIPKx = weak_odr constant
-// CHECK: @_ZTIw = weak_odr constant
-// CHECK: @_ZTIPw = weak_odr constant
-// CHECK: @_ZTIPKw = weak_odr constant
-// CHECK: @_ZTIt = weak_odr constant
-// CHECK: @_ZTIPt = weak_odr constant
-// CHECK: @_ZTIPKt = weak_odr constant
-// CHECK: @_ZTIs = weak_odr constant
-// CHECK: @_ZTIPs = weak_odr constant
-// CHECK: @_ZTIPKs = weak_odr constant
-// CHECK: @_ZTIm = weak_odr constant
-// CHECK: @_ZTIPm = weak_odr constant
-// CHECK: @_ZTIPKm = weak_odr constant
-// CHECK: @_ZTIl = weak_odr constant
-// CHECK: @_ZTIPl = weak_odr constant
-// CHECK: @_ZTIPKl = weak_odr constant
-// CHECK: @_ZTIj = weak_odr constant
-// CHECK: @_ZTIPj = weak_odr constant
-// CHECK: @_ZTIPKj = weak_odr constant
-// CHECK: @_ZTIi = weak_odr constant
-// CHECK: @_ZTIPi = weak_odr constant
-// CHECK: @_ZTIPKi = weak_odr constant
-// CHECK: @_ZTIh = weak_odr constant
-// CHECK: @_ZTIPh = weak_odr constant
-// CHECK: @_ZTIPKh = weak_odr constant
-// CHECK: @_ZTIf = weak_odr constant
-// CHECK: @_ZTIPf = weak_odr constant
-// CHECK: @_ZTIPKf = weak_odr constant
-// CHECK: @_ZTIe = weak_odr constant
-// CHECK: @_ZTIPe = weak_odr constant
-// CHECK: @_ZTIPKe = weak_odr constant
-// CHECK: @_ZTId = weak_odr constant
-// CHECK: @_ZTIPd = weak_odr constant
-// CHECK: @_ZTIPKd = weak_odr constant
-// CHECK: @_ZTIc = weak_odr constant
-// CHECK: @_ZTIPc = weak_odr constant
-// CHECK: @_ZTIPKc = weak_odr constant
-// CHECK: @_ZTIb = weak_odr constant
-// CHECK: @_ZTIPb = weak_odr constant
-// CHECK: @_ZTIPKb = weak_odr constant
-// CHECK: @_ZTIa = weak_odr constant
-// CHECK: @_ZTIPa = weak_odr constant
-// CHECK: @_ZTIPKa = weak_odr constant
+// CHECK: @_ZTIv = constant
+// CHECK: @_ZTIPv = constant
+// CHECK: @_ZTIPKv = constant
+// CHECK: @_ZTIDi = constant
+// CHECK: @_ZTIPDi = constant
+// CHECK: @_ZTIPKDi = constant
+// CHECK: @_ZTIDs = constant
+// CHECK: @_ZTIPDs = constant
+// CHECK: @_ZTIPKDs = constant
+// CHECK: @_ZTIy = constant
+// CHECK: @_ZTIPy = constant
+// CHECK: @_ZTIPKy = constant
+// CHECK: @_ZTIx = constant
+// CHECK: @_ZTIPx = constant
+// CHECK: @_ZTIPKx = constant
+// CHECK: @_ZTIw = constant
+// CHECK: @_ZTIPw = constant
+// CHECK: @_ZTIPKw = constant
+// CHECK: @_ZTIt = constant
+// CHECK: @_ZTIPt = constant
+// CHECK: @_ZTIPKt = constant
+// CHECK: @_ZTIs = constant
+// CHECK: @_ZTIPs = constant
+// CHECK: @_ZTIPKs = constant
+// CHECK: @_ZTIm = constant
+// CHECK: @_ZTIPm = constant
+// CHECK: @_ZTIPKm = constant
+// CHECK: @_ZTIl = constant
+// CHECK: @_ZTIPl = constant
+// CHECK: @_ZTIPKl = constant
+// CHECK: @_ZTIj = constant
+// CHECK: @_ZTIPj = constant
+// CHECK: @_ZTIPKj = constant
+// CHECK: @_ZTIi = constant
+// CHECK: @_ZTIPi = constant
+// CHECK: @_ZTIPKi = constant
+// CHECK: @_ZTIh = constant
+// CHECK: @_ZTIPh = constant
+// CHECK: @_ZTIPKh = constant
+// CHECK: @_ZTIf = constant
+// CHECK: @_ZTIPf = constant
+// CHECK: @_ZTIPKf = constant
+// CHECK: @_ZTIe = constant
+// CHECK: @_ZTIPe = constant
+// CHECK: @_ZTIPKe = constant
+// CHECK: @_ZTId = constant
+// CHECK: @_ZTIPd = constant
+// CHECK: @_ZTIPKd = constant
+// CHECK: @_ZTIc = constant
+// CHECK: @_ZTIPc = constant
+// CHECK: @_ZTIPKc = constant
+// CHECK: @_ZTIb = constant
+// CHECK: @_ZTIPb = constant
+// CHECK: @_ZTIPKb = constant
+// CHECK: @_ZTIa = constant
+// CHECK: @_ZTIPa = constant
+// CHECK: @_ZTIPKa = constant
-// CHECK: _ZTI1A = weak_odr constant
+// CHECK: _ZTI1A = weak_odr hidden constant
// CHECK: _ZTI1B = constant
// CHECK: _ZTI1C = internal constant
-// CHECK: _ZTIA10_i = weak_odr constant
+// CHECK: _ZTI1TILj0EE = weak_odr hidden constant
+// CHECK: _ZTI1TILj1EE = weak_odr constant
+// CHECK: _ZTI1TILj2EE = external constant
+// CHECK: _ZTIA10_i = weak_odr hidden constant
// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant
// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant
-// CHECK: _ZTIFvvE = weak_odr
+// CHECK: _ZTIFvvE = weak_odr hidden constant
// CHECK: _ZTIM1A1C = internal constant
// CHECK: _ZTIM1AP1C = internal constant
// CHECK: _ZTIM1CPS_ = internal constant
// CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant
// CHECK: _ZTIP1C = internal constant
-// CHECK: _ZTIPFvvE = weak_odr constant
+// CHECK: _ZTIPFvvE = weak_odr hidden constant
// CHECK: _ZTIPM1Ci = internal constant
// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTIPP1C = internal constant
return typeid(A::a);
}
}
+
+template <unsigned N> class T {
+ virtual void anchor() {}
+};
+template class T<1>;
+template <> class T<2> { virtual void anchor(); };
+void t3() {
+ (void) typeid(T<0>);
+ (void) typeid(T<1>);
+ (void) typeid(T<2>);
+}
// and hidden visibility (rdar://problem/7523229).
// CHECK-2: @_ZTV1C = weak_odr hidden constant
// CHECK-2: @_ZTS1C = weak_odr constant
-// CHECK-2: @_ZTI1C = weak_odr constant
+// CHECK-2: @_ZTI1C = weak_odr hidden constant
// D has a key function that is defined in this translation unit so its vtable is
// defined in the translation unit.
// so its vtable should have weak_odr linkage and hidden visibility.
// CHECK-8: @_ZTV1FIlE = weak_odr hidden constant
// CHECK-8: @_ZTS1FIlE = weak_odr constant
-// CHECK-8: @_ZTI1FIlE = weak_odr constant
+// CHECK-8: @_ZTI1FIlE = weak_odr hidden constant
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have external linkage.
// its vtable should have weak_odr linkage and hidden visibility.
// CHECK-13: @_ZTV1FIcE = weak_odr hidden constant
// CHECK-13: @_ZTS1FIcE = weak_odr constant
-// CHECK-13: @_ZTI1FIcE = weak_odr constant
+// CHECK-13: @_ZTI1FIcE = weak_odr hidden constant
// RUN: FileCheck --check-prefix=CHECK-G %s < %t
//
void f() {
// CHECK: @_ZTS1X = weak_odr constant
- // CHECK: @_ZTI1X = weak_odr constant
+ // CHECK: @_ZTI1X = weak_odr hidden constant
(void)typeid(X&);
}