#include "CodeGenModule.h"
#include "CGCXXABI.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "CGObjCRuntime.h"
using namespace clang;
using namespace CodeGen;
namespace {
class RTTIBuilder {
CodeGenModule &CGM; llvm::LLVMContext &VMContext;
SmallVector<llvm::Constant *, 16> Fields;
llvm::GlobalVariable *
GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
void BuildVTablePointer(const Type *Ty);
void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
void BuildPointerTypeInfo(QualType PointeeTy);
void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
public:
RTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
VMContext(CGM.getModule().getContext()) { }
enum {
PTI_Const = 0x1,
PTI_Volatile = 0x2,
PTI_Restrict = 0x4,
PTI_Incomplete = 0x8,
PTI_ContainingClassIncomplete = 0x10
};
enum {
VMI_NonDiamondRepeat = 0x1,
VMI_DiamondShaped = 0x2
};
enum {
BCTI_Virtual = 0x1,
BCTI_Public = 0x2
};
llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
};
}
llvm::GlobalVariable *
RTTIBuilder::GetAddrOfTypeName(QualType Ty,
llvm::GlobalVariable::LinkageTypes Linkage) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
Out.flush();
StringRef Name = OutName.str();
llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
Name.substr(4));
llvm::GlobalVariable *GV =
CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
GV->setInitializer(Init);
return GV;
}
llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
Out.flush();
StringRef Name = OutName.str();
llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
if (!GV) {
GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
true,
llvm::GlobalValue::ExternalLinkage, 0, Name);
}
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
}
static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
switch (Ty->getKind()) {
case BuiltinType::Void:
case BuiltinType::NullPtr:
case BuiltinType::Bool:
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
case BuiltinType::Char_U:
case BuiltinType::Char_S:
case BuiltinType::UChar:
case BuiltinType::SChar:
case BuiltinType::Short:
case BuiltinType::UShort:
case BuiltinType::Int:
case BuiltinType::UInt:
case BuiltinType::Long:
case BuiltinType::ULong:
case BuiltinType::LongLong:
case BuiltinType::ULongLong:
case BuiltinType::Half:
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Int128:
case BuiltinType::UInt128:
return true;
case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
llvm_unreachable("asking for RRTI for a placeholder type!");
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
llvm_unreachable("FIXME: Objective-C types are unsupported!");
}
llvm_unreachable("Invalid BuiltinType Kind!");
}
static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
QualType PointeeTy = PointerTy->getPointeeType();
const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
if (!BuiltinTy)
return false;
Qualifiers Quals = PointeeTy.getQualifiers();
Quals.removeConst();
if (!Quals.empty())
return false;
return TypeInfoIsInStandardLibrary(BuiltinTy);
}
static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
return TypeInfoIsInStandardLibrary(BuiltinTy);
if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
return TypeInfoIsInStandardLibrary(PointerTy);
return false;
}
static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
ASTContext &Context = CGM.getContext();
if (!Context.getLangOptions().RTTI) return false;
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
if (!RD->hasDefinition())
return false;
if (!RD->isDynamicClass())
return false;
return !CGM.getVTables().ShouldEmitVTableInThisTU(RD);
}
return false;
}
static bool IsIncompleteClassType(const RecordType *RecordTy) {
return !RecordTy->getDecl()->isCompleteDefinition();
}
static bool ContainsIncompleteClassType(QualType Ty) {
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
if (IsIncompleteClassType(RecordTy))
return true;
}
if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
return ContainsIncompleteClassType(PointerTy->getPointeeType());
if (const MemberPointerType *MemberPointerTy =
dyn_cast<MemberPointerType>(Ty)) {
const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
if (IsIncompleteClassType(ClassType))
return true;
return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
}
return false;
}
static llvm::GlobalVariable::LinkageTypes
getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
if (ContainsIncompleteClassType(Ty))
return llvm::GlobalValue::InternalLinkage;
switch (Ty->getLinkage()) {
case NoLinkage:
case InternalLinkage:
case UniqueExternalLinkage:
return llvm::GlobalValue::InternalLinkage;
case ExternalLinkage:
if (!CGM.getLangOptions().RTTI) {
return llvm::GlobalValue::LinkOnceODRLinkage;
}
if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
if (RD->hasAttr<WeakAttr>())
return llvm::GlobalValue::WeakODRLinkage;
if (RD->isDynamicClass())
return CGM.getVTableLinkage(RD);
}
return llvm::GlobalValue::LinkOnceODRLinkage;
}
llvm_unreachable("Invalid linkage!");
}
static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
if (RD->getNumBases() != 1)
return false;
CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
if (Base->isVirtual())
return false;
if (Base->getAccessSpecifier() != AS_public)
return false;
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (!BaseDecl->isEmpty() &&
BaseDecl->isDynamicClass() != RD->isDynamicClass())
return false;
return true;
}
void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
static const char * const ClassTypeInfo =
"_ZTVN10__cxxabiv117__class_type_infoE";
static const char * const SIClassTypeInfo =
"_ZTVN10__cxxabiv120__si_class_type_infoE";
static const char * const VMIClassTypeInfo =
"_ZTVN10__cxxabiv121__vmi_class_type_infoE";
const char *VTableName = 0;
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
llvm_unreachable("Non-canonical and dependent types shouldn't get here");
case Type::LValueReference:
case Type::RValueReference:
llvm_unreachable("References shouldn't get here");
case Type::Builtin:
case Type::Vector:
case Type::ExtVector:
case Type::Complex:
case Type::Atomic:
case Type::BlockPointer:
VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
break;
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
break;
case Type::FunctionNoProto:
case Type::FunctionProto:
VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
break;
case Type::Enum:
VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
break;
case Type::Record: {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
if (!RD->hasDefinition() || !RD->getNumBases()) {
VTableName = ClassTypeInfo;
} else if (CanUseSingleInheritance(RD)) {
VTableName = SIClassTypeInfo;
} else {
VTableName = VMIClassTypeInfo;
}
break;
}
case Type::ObjCObject:
Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
if (isa<BuiltinType>(Ty)) {
VTableName = ClassTypeInfo;
break;
}
assert(isa<ObjCInterfaceType>(Ty));
case Type::ObjCInterface:
if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
VTableName = SIClassTypeInfo;
} else {
VTableName = ClassTypeInfo;
}
break;
case Type::ObjCObjectPointer:
case Type::Pointer:
VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
break;
case Type::MemberPointer:
VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
break;
}
llvm::Constant *VTable =
CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
llvm::Type *PtrDiffTy =
CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
Fields.push_back(VTable);
}
static void
maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,
QualType Ty) {
if (!GV->hasAvailableExternallyLinkage())
return;
llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
return;
GV->setLinkage(Linkage);
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
Out.flush();
StringRef Name = OutName.str();
llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);
assert(TypeNameGV->hasAvailableExternallyLinkage() &&
"Type name has different linkage from type info!");
TypeNameGV->setLinkage(Linkage);
}
llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
Ty = CGM.getContext().getCanonicalType(Ty);
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
Out.flush();
StringRef Name = OutName.str();
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
if (OldGV && !OldGV->isDeclaration()) {
maybeUpdateRTTILinkage(CGM, OldGV, Ty);
return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
}
bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
return GetAddrOfExternalRTTIDescriptor(Ty);
llvm::GlobalVariable::LinkageTypes Linkage;
if (IsStdLib)
Linkage = llvm::GlobalValue::ExternalLinkage;
else
Linkage = getTypeInfoLinkage(CGM, Ty);
BuildVTablePointer(cast<Type>(Ty));
llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy));
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
llvm_unreachable("Non-canonical and dependent types shouldn't get here");
case Type::Builtin:
case Type::Vector:
case Type::ExtVector:
case Type::Complex:
case Type::BlockPointer:
break;
case Type::LValueReference:
case Type::RValueReference:
llvm_unreachable("References shouldn't get here");
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
break;
case Type::FunctionNoProto:
case Type::FunctionProto:
break;
case Type::Enum:
break;
case Type::Record: {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
if (!RD->hasDefinition() || !RD->getNumBases()) {
break;
}
if (CanUseSingleInheritance(RD))
BuildSIClassTypeInfo(RD);
else
BuildVMIClassTypeInfo(RD);
break;
}
case Type::ObjCObject:
case Type::ObjCInterface:
BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
break;
case Type::ObjCObjectPointer:
BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
break;
case Type::Pointer:
BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
break;
case Type::MemberPointer:
BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
break;
case Type::Atomic:
break;
}
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
true, Linkage, Init, Name);
if (OldGV) {
GV->takeName(OldGV);
llvm::Constant *NewPtr =
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
OldGV->replaceAllUsesWith(NewPtr);
OldGV->eraseFromParent();
}
if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI);
CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName);
} else {
Visibility TypeInfoVisibility = DefaultVisibility;
if (CGM.getCodeGenOpts().HiddenWeakVTables &&
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
TypeInfoVisibility = HiddenVisibility;
Visibility ExplicitVisibility = Ty->getVisibility();
TypeName->setVisibility(CodeGenModule::
GetLLVMVisibility(ExplicitVisibility));
TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility());
GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility));
}
GV->setUnnamedAddr(true);
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
}
static unsigned ComputeQualifierFlags(Qualifiers Quals) {
unsigned Flags = 0;
if (Quals.hasConst())
Flags |= RTTIBuilder::PTI_Const;
if (Quals.hasVolatile())
Flags |= RTTIBuilder::PTI_Volatile;
if (Quals.hasRestrict())
Flags |= RTTIBuilder::PTI_Restrict;
return Flags;
}
void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
const Type *T = OT->getBaseType().getTypePtr();
assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
if (isa<BuiltinType>(T)) return;
ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
ObjCInterfaceDecl *Super = Class->getSuperClass();
if (!Super) return;
QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
Fields.push_back(BaseTypeInfo);
}
void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
llvm::Constant *BaseTypeInfo =
RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
Fields.push_back(BaseTypeInfo);
}
namespace {
struct SeenBases {
llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
};
}
static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
SeenBases &Bases) {
unsigned Flags = 0;
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (Base->isVirtual()) {
if (Bases.VirtualBases.count(BaseDecl)) {
Flags |= RTTIBuilder::VMI_DiamondShaped;
} else {
if (Bases.NonVirtualBases.count(BaseDecl))
Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
Bases.VirtualBases.insert(BaseDecl);
}
} else {
if (Bases.NonVirtualBases.count(BaseDecl)) {
Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
} else {
if (Bases.VirtualBases.count(BaseDecl))
Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
Bases.NonVirtualBases.insert(BaseDecl);
}
}
for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(),
E = BaseDecl->bases_end(); I != E; ++I)
Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
return Flags;
}
static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
unsigned Flags = 0;
SeenBases Bases;
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I)
Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
return Flags;
}
void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
if (!RD->getNumBases())
return;
llvm::Type *LongLTy =
CGM.getTypes().ConvertType(CGM.getContext().LongTy);
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = I;
Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType()));
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
int64_t OffsetFlags = 0;
CharUnits Offset;
if (Base->isVirtual())
Offset =
CGM.getVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
else {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
Offset = Layout.getBaseClassOffset(BaseDecl);
};
OffsetFlags = Offset.getQuantity() << 8;
if (Base->isVirtual())
OffsetFlags |= BCTI_Virtual;
if (Base->getAccessSpecifier() == AS_public)
OffsetFlags |= BCTI_Public;
Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
}
}
void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
Qualifiers Quals;
QualType UnqualifiedPointeeTy =
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
unsigned Flags = ComputeQualifierFlags(Quals);
if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
Flags |= PTI_Incomplete;
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
llvm::Constant *PointeeTypeInfo =
RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
Fields.push_back(PointeeTypeInfo);
}
void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
QualType PointeeTy = Ty->getPointeeType();
Qualifiers Quals;
QualType UnqualifiedPointeeTy =
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
unsigned Flags = ComputeQualifierFlags(Quals);
const RecordType *ClassType = cast<RecordType>(Ty->getClass());
if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
Flags |= PTI_Incomplete;
if (IsIncompleteClassType(ClassType))
Flags |= PTI_ContainingClassIncomplete;
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
llvm::Constant *PointeeTypeInfo =
RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
Fields.push_back(PointeeTypeInfo);
Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
}
llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
bool ForEH) {
if (!ForEH && !getContext().getLangOptions().RTTI)
return llvm::Constant::getNullValue(Int8PtrTy);
if (ForEH && Ty->isObjCObjectPointerType() && !Features.NeXTRuntime)
return ObjCRuntime->GetEHType(Ty);
return RTTIBuilder(*this).BuildTypeInfo(Ty);
}
void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
QualType PointerType = Context.getPointerType(Type);
QualType PointerTypeConst = Context.getPointerType(Type.withConst());
RTTIBuilder(*this).BuildTypeInfo(Type, true);
RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
}
void CodeGenModule::EmitFundamentalRTTIDescriptors() {
QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,
Context.BoolTy, Context.WCharTy,
Context.CharTy, Context.UnsignedCharTy,
Context.SignedCharTy, Context.ShortTy,
Context.UnsignedShortTy, Context.IntTy,
Context.UnsignedIntTy, Context.LongTy,
Context.UnsignedLongTy, Context.LongLongTy,
Context.UnsignedLongLongTy, Context.FloatTy,
Context.DoubleTy, Context.LongDoubleTy,
Context.Char16Ty, Context.Char32Ty };
for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)
EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
}