forked from OSchip/llvm-project
Add a completed/incomplete type difference. This allows us to have
partial types for contexts and forward decls while allowing us to complete types later on for debug purposes. This piggy-backs on the metadata replacement and rauw changes for temporary nodes and takes advantage of the incremental support I added in earlier. This allows us to, if we decide, to limit adding methods and variables to structures in order to limit the amount of debug information output into a .o file. The caching is a bit complicated though so any thoughts on untangling that are welcome. llvm-svn: 150631
This commit is contained in:
parent
923d199a67
commit
7381907e65
|
@ -524,11 +524,8 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
|
||||||
|
|
||||||
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
|
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
|
||||||
if (!RD->isDependentType()) {
|
if (!RD->isDependentType()) {
|
||||||
llvm::DIDescriptor FDContext =
|
llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
|
||||||
createContextChain(cast<Decl>(RD->getDeclContext()));
|
getOrCreateMainFile());
|
||||||
llvm::DIType Ty = createRecordFwdDecl(RD, FDContext);
|
|
||||||
|
|
||||||
RegionMap[Context] = llvm::WeakVH(Ty);
|
|
||||||
return llvm::DIDescriptor(Ty);
|
return llvm::DIDescriptor(Ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,7 +554,9 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
|
||||||
RecordDecl *RD = RTy->getDecl();
|
RecordDecl *RD = RTy->getDecl();
|
||||||
llvm::DIDescriptor FDContext =
|
llvm::DIDescriptor FDContext =
|
||||||
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
||||||
return createRecordFwdDecl(RD, FDContext);
|
llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
|
||||||
|
TypeCache[PointeeTy.getAsOpaquePtr()] = RetTy;
|
||||||
|
return RetTy;
|
||||||
}
|
}
|
||||||
return getOrCreateType(PointeeTy, Unit);
|
return getOrCreateType(PointeeTy, Unit);
|
||||||
|
|
||||||
|
@ -654,10 +653,11 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
|
||||||
// declared.
|
// declared.
|
||||||
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
|
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
|
||||||
const TypedefNameDecl *TyDecl = Ty->getDecl();
|
const TypedefNameDecl *TyDecl = Ty->getDecl();
|
||||||
|
|
||||||
llvm::DIDescriptor TypedefContext =
|
llvm::DIDescriptor TypedefContext =
|
||||||
getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
|
getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
|
||||||
|
|
||||||
return
|
return
|
||||||
DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
|
DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,8 +1133,6 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
||||||
|
|
||||||
// Get overall information about the record type for the debug info.
|
// Get overall information about the record type for the debug info.
|
||||||
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
||||||
unsigned Line = getLineNumber(RD->getLocation());
|
|
||||||
StringRef RDName = RD->getName();
|
|
||||||
|
|
||||||
// Records and classes and unions can all be recursive. To handle them, we
|
// Records and classes and unions can all be recursive. To handle them, we
|
||||||
// first generate a debug descriptor for the struct as a forward declaration.
|
// first generate a debug descriptor for the struct as a forward declaration.
|
||||||
|
@ -1143,28 +1141,21 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
||||||
// may refer to the forward decl if the struct is recursive) and replace all
|
// may refer to the forward decl if the struct is recursive) and replace all
|
||||||
// uses of the forward declaration with the final definition.
|
// uses of the forward declaration with the final definition.
|
||||||
|
|
||||||
llvm::DIDescriptor RDContext;
|
llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit);
|
||||||
if (CGM.getCodeGenOpts().LimitDebugInfo)
|
|
||||||
RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
|
|
||||||
else
|
|
||||||
RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
|
||||||
|
|
||||||
// If this is just a forward declaration, construct an appropriately
|
|
||||||
// marked node and just return it.
|
|
||||||
if (!RD->getDefinition())
|
|
||||||
return createRecordFwdDecl(RD, RDContext);
|
|
||||||
|
|
||||||
llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
|
|
||||||
|
|
||||||
|
if (FwdDecl.isForwardDecl())
|
||||||
|
return FwdDecl;
|
||||||
|
|
||||||
llvm::MDNode *MN = FwdDecl;
|
llvm::MDNode *MN = FwdDecl;
|
||||||
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
||||||
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
|
||||||
// it.
|
|
||||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
|
||||||
// Push the struct on region stack.
|
// Push the struct on region stack.
|
||||||
LexicalBlockStack.push_back(FwdDeclNode);
|
LexicalBlockStack.push_back(FwdDeclNode);
|
||||||
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
|
||||||
|
|
||||||
|
// Add this to the completed types cache since we're completing it.
|
||||||
|
CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
||||||
|
|
||||||
// Convert all the elements.
|
// Convert all the elements.
|
||||||
SmallVector<llvm::Value *, 16> EltTys;
|
SmallVector<llvm::Value *, 16> EltTys;
|
||||||
|
|
||||||
|
@ -1196,50 +1187,20 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
||||||
if (RI != RegionMap.end())
|
if (RI != RegionMap.end())
|
||||||
RegionMap.erase(RI);
|
RegionMap.erase(RI);
|
||||||
|
|
||||||
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
|
||||||
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
|
||||||
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
|
||||||
llvm::MDNode *RealDecl = NULL;
|
// FIXME: Magic numbers ahoy! These should be changed when we
|
||||||
|
// get some enums in llvm/Analysis/DebugInfo.h to refer to
|
||||||
|
// them.
|
||||||
if (RD->isUnion())
|
if (RD->isUnion())
|
||||||
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
|
MN->replaceOperandWith(10, Elements);
|
||||||
Size, Align, 0, Elements);
|
|
||||||
else if (CXXDecl) {
|
else if (CXXDecl) {
|
||||||
RDName = getClassName(RD);
|
MN->replaceOperandWith(10, Elements);
|
||||||
// A class's primary base or the class itself contains the vtable.
|
MN->replaceOperandWith(13, TParamsArray);
|
||||||
llvm::MDNode *ContainingType = NULL;
|
|
||||||
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
|
||||||
if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
|
|
||||||
// Seek non virtual primary base root.
|
|
||||||
while (1) {
|
|
||||||
const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
|
|
||||||
const CXXRecordDecl *PBT = BRL.getPrimaryBase();
|
|
||||||
if (PBT && !BRL.isPrimaryBaseVirtual())
|
|
||||||
PBase = PBT;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ContainingType =
|
|
||||||
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
|
|
||||||
}
|
|
||||||
else if (CXXDecl->isDynamicClass())
|
|
||||||
ContainingType = FwdDecl;
|
|
||||||
|
|
||||||
// FIXME: This could be a struct type giving a default visibility different
|
|
||||||
// than C++ class type, but needs llvm metadata changes first.
|
|
||||||
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
|
|
||||||
Size, Align, 0, 0, llvm::DIType(),
|
|
||||||
Elements, ContainingType,
|
|
||||||
TParamsArray);
|
|
||||||
} else
|
} else
|
||||||
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
|
MN->replaceOperandWith(10, Elements);
|
||||||
Size, Align, 0, Elements);
|
|
||||||
|
|
||||||
// Now that we have a real decl for the struct, replace anything using the
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(MN);
|
||||||
// old decl with the new one. This will recursively update the debug info.
|
return llvm::DIType(MN);
|
||||||
llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
|
||||||
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
|
|
||||||
return llvm::DIType(RealDecl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CreateType - get objective-c object type.
|
/// CreateType - get objective-c object type.
|
||||||
|
@ -1637,6 +1598,26 @@ llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
|
||||||
return llvm::DIType();
|
return llvm::DIType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getCompletedTypeOrNull - Get the type from the cache or return null if it
|
||||||
|
/// doesn't exist.
|
||||||
|
llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
|
||||||
|
|
||||||
|
// Unwrap the type as needed for debug information.
|
||||||
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
||||||
|
|
||||||
|
// Check for existing entry.
|
||||||
|
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
|
||||||
|
CompletedTypeCache.find(Ty.getAsOpaquePtr());
|
||||||
|
if (it != CompletedTypeCache.end()) {
|
||||||
|
// Verify that the debug info still exists.
|
||||||
|
if (&*it->second)
|
||||||
|
return llvm::DIType(cast<llvm::MDNode>(it->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
return llvm::DIType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// getOrCreateType - Get the type from the cache or create a new
|
/// getOrCreateType - Get the type from the cache or create a new
|
||||||
/// one if necessary.
|
/// one if necessary.
|
||||||
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
||||||
|
@ -1646,14 +1627,21 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
||||||
// Unwrap the type as needed for debug information.
|
// Unwrap the type as needed for debug information.
|
||||||
Ty = UnwrapTypeForDebugInfo(Ty);
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
||||||
|
|
||||||
llvm::DIType T = getTypeOrNull(Ty);
|
llvm::DIType T = getCompletedTypeOrNull(Ty);
|
||||||
|
|
||||||
if (T.Verify()) return T;
|
if (T.Verify()) return T;
|
||||||
|
|
||||||
// Otherwise create the type.
|
// Otherwise create the type.
|
||||||
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
||||||
|
|
||||||
|
if (T.Verify() && T.isForwardDecl())
|
||||||
|
T.replaceAllUsesWith(Res);
|
||||||
|
|
||||||
// And update the type cache.
|
// And update the type cache.
|
||||||
TypeCache[Ty.getAsOpaquePtr()] = Res;
|
TypeCache[Ty.getAsOpaquePtr()] = Res;
|
||||||
|
|
||||||
|
if (!Res.isForwardDecl())
|
||||||
|
CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1737,6 +1725,127 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
|
||||||
return llvm::DIType();
|
return llvm::DIType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getOrCreateLimitedType - Get the type from the cache or create a new
|
||||||
|
/// limited type if necessary.
|
||||||
|
llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,
|
||||||
|
llvm::DIFile Unit) {
|
||||||
|
if (Ty.isNull())
|
||||||
|
return llvm::DIType();
|
||||||
|
|
||||||
|
// Unwrap the type as needed for debug information.
|
||||||
|
Ty = UnwrapTypeForDebugInfo(Ty);
|
||||||
|
|
||||||
|
llvm::DIType T = getTypeOrNull(Ty);
|
||||||
|
if (T.Verify() && !T.isForwardDecl()) return T;
|
||||||
|
|
||||||
|
// Otherwise create the type.
|
||||||
|
llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);
|
||||||
|
|
||||||
|
if (T.Verify() && T.isForwardDecl())
|
||||||
|
T.replaceAllUsesWith(Res);
|
||||||
|
|
||||||
|
// And update the type cache.
|
||||||
|
TypeCache[Ty.getAsOpaquePtr()] = Res;
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Currently used for context chains when limiting debug info.
|
||||||
|
llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
|
||||||
|
RecordDecl *RD = Ty->getDecl();
|
||||||
|
|
||||||
|
// Get overall information about the record type for the debug info.
|
||||||
|
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
||||||
|
unsigned Line = getLineNumber(RD->getLocation());
|
||||||
|
StringRef RDName = RD->getName();
|
||||||
|
|
||||||
|
llvm::DIDescriptor RDContext;
|
||||||
|
if (CGM.getCodeGenOpts().LimitDebugInfo)
|
||||||
|
RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
|
||||||
|
else
|
||||||
|
RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
||||||
|
|
||||||
|
// If this is just a forward declaration, construct an appropriately
|
||||||
|
// marked node and just return it.
|
||||||
|
if (!RD->getDefinition()) {
|
||||||
|
llvm::DIType RTy = createRecordFwdDecl(RD, RDContext);
|
||||||
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RTy;
|
||||||
|
return RTy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary type here - different than normal forward declared
|
||||||
|
// types.
|
||||||
|
llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
|
||||||
|
|
||||||
|
llvm::MDNode *MN = FwdDecl;
|
||||||
|
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
|
||||||
|
// Otherwise, insert it into the TypeCache so that recursive uses will find
|
||||||
|
// it.
|
||||||
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
|
||||||
|
|
||||||
|
uint64_t Size = CGM.getContext().getTypeSize(Ty);
|
||||||
|
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
|
||||||
|
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
|
||||||
|
llvm::MDNode *RealDecl = NULL;
|
||||||
|
|
||||||
|
if (RD->isUnion())
|
||||||
|
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
|
||||||
|
Size, Align, 0, llvm::DIArray());
|
||||||
|
else if (CXXDecl) {
|
||||||
|
RDName = getClassName(RD);
|
||||||
|
// A class's primary base or the class itself contains the vtable.
|
||||||
|
llvm::MDNode *ContainingType = NULL;
|
||||||
|
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
|
||||||
|
if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
|
||||||
|
// Seek non virtual primary base root.
|
||||||
|
while (1) {
|
||||||
|
const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
|
||||||
|
const CXXRecordDecl *PBT = BRL.getPrimaryBase();
|
||||||
|
if (PBT && !BRL.isPrimaryBaseVirtual())
|
||||||
|
PBase = PBT;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ContainingType =
|
||||||
|
getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
|
||||||
|
}
|
||||||
|
else if (CXXDecl->isDynamicClass())
|
||||||
|
ContainingType = FwdDecl;
|
||||||
|
|
||||||
|
// FIXME: This could be a struct type giving a default visibility different
|
||||||
|
// than C++ class type, but needs llvm metadata changes first.
|
||||||
|
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
|
||||||
|
Size, Align, 0, 0, llvm::DIType(),
|
||||||
|
llvm::DIArray(), ContainingType,
|
||||||
|
llvm::DIArray());
|
||||||
|
} else
|
||||||
|
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
|
||||||
|
Size, Align, 0, llvm::DIArray());
|
||||||
|
|
||||||
|
llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
|
||||||
|
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
|
||||||
|
return llvm::DIType(RealDecl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CreateLimitedTypeNode - Create a new debug type node, but only forward
|
||||||
|
/// declare composite types that haven't been processed yet.
|
||||||
|
llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
|
||||||
|
|
||||||
|
// Work out details of type.
|
||||||
|
switch (Ty->getTypeClass()) {
|
||||||
|
#define TYPE(Class, Base)
|
||||||
|
#define ABSTRACT_TYPE(Class, Base)
|
||||||
|
#define NON_CANONICAL_TYPE(Class, Base)
|
||||||
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
||||||
|
#include "clang/AST/TypeNodes.def"
|
||||||
|
llvm_unreachable("Dependent types cannot show up in debug information");
|
||||||
|
|
||||||
|
case Type::Record:
|
||||||
|
return CreateLimitedType(cast<RecordType>(Ty));
|
||||||
|
default:
|
||||||
|
return CreateTypeNode(Ty, Unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
||||||
llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
|
llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
|
||||||
StringRef Name,
|
StringRef Name,
|
||||||
|
|
|
@ -53,6 +53,9 @@ class CGDebugInfo {
|
||||||
/// TypeCache - Cache of previously constructed Types.
|
/// TypeCache - Cache of previously constructed Types.
|
||||||
llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
|
llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
|
||||||
|
|
||||||
|
/// CompleteTypeCache - Cache of previously constructed complete RecordTypes.
|
||||||
|
llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;
|
||||||
|
|
||||||
bool BlockLiteralGenericSet;
|
bool BlockLiteralGenericSet;
|
||||||
llvm::DIType BlockLiteralGeneric;
|
llvm::DIType BlockLiteralGeneric;
|
||||||
|
|
||||||
|
@ -84,6 +87,7 @@ class CGDebugInfo {
|
||||||
llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
|
||||||
llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
|
||||||
llvm::DIType CreateType(const RecordType *Ty);
|
llvm::DIType CreateType(const RecordType *Ty);
|
||||||
|
llvm::DIType CreateLimitedType(const RecordType *Ty);
|
||||||
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
|
||||||
llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
|
||||||
llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
|
||||||
|
@ -94,6 +98,7 @@ class CGDebugInfo {
|
||||||
llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
|
llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
|
||||||
llvm::DIType CreateEnumType(const EnumDecl *ED);
|
llvm::DIType CreateEnumType(const EnumDecl *ED);
|
||||||
llvm::DIType getTypeOrNull(const QualType);
|
llvm::DIType getTypeOrNull(const QualType);
|
||||||
|
llvm::DIType getCompletedTypeOrNull(const QualType);
|
||||||
llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
|
llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
|
||||||
llvm::DIFile F);
|
llvm::DIFile F);
|
||||||
llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,
|
llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,
|
||||||
|
@ -257,9 +262,17 @@ private:
|
||||||
/// necessary.
|
/// necessary.
|
||||||
llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
|
llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
|
||||||
|
|
||||||
|
/// getOrCreateLimitedType - Get the type from the cache or create a new
|
||||||
|
/// partial type if necessary.
|
||||||
|
llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F);
|
||||||
|
|
||||||
/// CreateTypeNode - Create type metadata for a source language type.
|
/// CreateTypeNode - Create type metadata for a source language type.
|
||||||
llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
|
llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
|
||||||
|
|
||||||
|
/// CreateLimitedTypeNode - Create type metadata for a source language
|
||||||
|
/// type, but only partial types for records.
|
||||||
|
llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F);
|
||||||
|
|
||||||
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
/// CreateMemberType - Create new member and increase Offset by FType's size.
|
||||||
llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
|
llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
|
||||||
StringRef Name, uint64_t *Offset);
|
StringRef Name, uint64_t *Offset);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
||||||
// XFAIL: *
|
|
||||||
class Test
|
class Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -19,6 +19,6 @@ protected:
|
||||||
|
|
||||||
Test t;
|
Test t;
|
||||||
|
|
||||||
// CHECK: metadata !"data", metadata !7, i32 13, i64 32, i64 32, i32 0, i32 0
|
// CHECK: metadata !"data", metadata !7, i32 14, i64 32, i64 32, i32 0, i32 0
|
||||||
// CHECK: metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !5} ; [ DW_TAG_pointer_type ]
|
// CHECK: metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !5} ; [ DW_TAG_pointer_type ]
|
||||||
// CHECK-NOT: metadata !"data", metadata !7, i32 13, i64 0, i64 0, i32 0, i32 4,
|
// CHECK-NOT: metadata !"data", metadata !7, i32 13, i64 0, i64 0, i32 0, i32 4,
|
||||||
|
|
Loading…
Reference in New Issue