From 625c1ae781e3b8973bc9ec520268fe3301e4caf5 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 21 Dec 2009 00:41:42 +0000 Subject: [PATCH] Incomplete structs should also have internal linkage. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91805 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGRTTI.cpp | 85 ++++++++++++++++++++++++++++---- test/CodeGenCXX/rtti-linkage.cpp | 2 + 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 416bb1694c..ae5af6d775 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -314,10 +314,6 @@ public: const clang::Type &Type = *CGM.getContext().getCanonicalType(Ty).getTypePtr(); - if (const RecordType *RT = Ty.getTypePtr()->getAs()) - if (const CXXRecordDecl *RD = cast(RT->getDecl())) - return BuildClassTypeInfo(RD); - switch (Type.getTypeClass()) { default: { assert(0 && "typeid expression"); @@ -329,10 +325,20 @@ public: return GetAddrOfExternalRTTIDescriptor(Ty); } + case Type::Record: { + const RecordType *RT = cast(&Type); + + const CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->getNumBases()) + return BuildClassTypeInfo(RD); + + // Fall through. + } + case Type::Pointer: case Type::MemberPointer: - return BuildTypeInfo(Ty); + case Type::FunctionProto: case Type::FunctionNoProto: return BuildSimpleType(Ty, "_ZTVN10__cxxabiv120__function_type_infoE"); @@ -496,8 +502,17 @@ bool ShouldUseExternalRTTIDescriptor(QualType Ty) { return TypeInfoIsInStandardLibrary(PointerTy); if (const RecordType *RecordTy = dyn_cast(Ty)) { - (void)RecordTy; - assert(false && "FIXME"); + const CXXRecordDecl *RD = cast(RecordTy->getDecl()); + if (!RD->isDynamicClass()) + return false; + + // Get the key function. + const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD); + if (KeyFunction && !KeyFunction->getBody()) { + // The class has a key function, but it is not defined in this translation + // unit, so we should use the external descriptor for it. + return true; + } } return false; @@ -555,8 +570,40 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { // making it a local static object. if (ContainsIncompleteClassType(Ty)) return llvm::GlobalValue::InternalLinkage; - - // FIXME: Check linkage and anonymous namespace. + + if (const PointerType *PointerTy = dyn_cast(Ty)) { + // If the pointee type has internal linkage, then the pointer type needs to + // have it as well. + if (getTypeInfoLinkage(PointerTy->getPointeeType()) == + llvm::GlobalVariable::InternalLinkage) + return llvm::GlobalVariable::InternalLinkage; + + return llvm::GlobalVariable::WeakODRLinkage; + } + + if (const RecordType *RecordTy = dyn_cast(Ty)) { + const CXXRecordDecl *RD = cast(RecordTy->getDecl()); + + // If we're in an anonymous namespace, then we always want internal linkage. + if (RD->isInAnonymousNamespace() || !RD->hasLinkage()) + return llvm::GlobalVariable::InternalLinkage; + + 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; + } + + // Otherwise, the RTTI descriptor is emitted with external linkage. + return llvm::GlobalValue::ExternalLinkage; + } + + assert(false && "Unhandled type!"); return llvm::GlobalValue::WeakODRLinkage; } @@ -565,6 +612,17 @@ void RTTIBuilder::BuildVtablePointer(const Type *Ty) { switch (Ty->getTypeClass()) { default: assert(0 && "Unhandled type!"); + + case Type::Record: { + const CXXRecordDecl *RD = + cast(cast(Ty)->getDecl()); + if (!RD->getNumBases()) { + // abi::__class_type_info + VtableName = "_ZTVN10__cxxabiv117__class_type_infoE"; + break; + } + } + case Type::Pointer: // abi::__pointer_type_info VtableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; @@ -620,6 +678,15 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty) { assert(false && "Builtin type info must be in the standard library!"); break; + case Type::Record: { + const CXXRecordDecl *RD = + cast(cast(Ty)->getDecl()); + if (!RD->getNumBases()) { + // We don't need to emit any fields. + break; + } + } + case Type::Pointer: BuildPointerTypeInfo(cast(Ty)); break; diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index 5b4a8e42dd..2875e19ae3 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -6,6 +6,8 @@ // CHECK: _ZTI1A = weak_odr constant // CHECK: _ZTI1B = constant // CHECK: _ZTSP1C = internal constant +// CHECK: _ZTS1C = internal constant +// CHECK: _ZTI1C = internal constant // CHECK: _ZTIP1C = internal constant // CHECK: _ZTSPP1C = internal constant // CHECK: _ZTIPP1C = internal constant -- 2.40.0