diff options
author | Anders Carlsson <andersca@mac.com> | 2009-12-21 00:41:42 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-12-21 00:41:42 +0000 |
commit | 625c1ae781e3b8973bc9ec520268fe3301e4caf5 (patch) | |
tree | 7e0010313b47d4a7ebc66f0ddd40e405d7509263 /lib/CodeGen/CGRTTI.cpp | |
parent | 17fa6f971c1912c77aa10bdac4b7991b5e1646e2 (diff) |
Incomplete structs should also have internal linkage.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91805 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGRTTI.cpp')
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 85 |
1 files changed, 76 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<RecordType>()) - if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(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<RecordType>(&Type); + + const CXXRecordDecl *RD = cast<CXXRecordDecl>(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<RecordType>(Ty)) { - (void)RecordTy; - assert(false && "FIXME"); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(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<PointerType>(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<RecordType>(Ty)) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(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<CXXRecordDecl>(cast<RecordType>(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<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); + if (!RD->getNumBases()) { + // We don't need to emit any fields. + break; + } + } + case Type::Pointer: BuildPointerTypeInfo(cast<PointerType>(Ty)); break; |