mirror of
https://github.com/intel/llvm.git
synced 2026-02-07 16:11:27 +08:00
PR16214: Debug Info: -flimit-debug-info doesn't omit definitions for types used via typedefs
In an effort to make -flimit-debug-info more consistent I over-shot the mark & made types used via typedefs never produce definitions in the debug info (even if the type was used in a way that would require a definition). The fix for this is to do exactly what I was hoping to do at some point - plumb the declaration/definition choice through the various layers of "CreateType" in CGDebugInfo. In this way we can produce declarations whenever they are sufficient & definitions otherwise - including when qualifiers are used, for example (discovered in PR14467). This may not be complete (there may be other types/situations where we need to propagate the "declaration/definition" choice) but it lays the basic foundation which we can enhance in future iterations. llvm-svn: 183296
This commit is contained in:
@@ -501,7 +501,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
|
||||
|
||||
/// CreateCVRType - Get the qualified type from the cache or create
|
||||
/// a new one if necessary.
|
||||
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
|
||||
llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit, bool Declaration) {
|
||||
QualifierCollector Qc;
|
||||
const Type *T = Qc.strip(Ty);
|
||||
|
||||
@@ -527,7 +527,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
|
||||
return getOrCreateType(QualType(T, 0), Unit);
|
||||
}
|
||||
|
||||
llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
|
||||
llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit, Declaration);
|
||||
|
||||
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
|
||||
// CVR derived types.
|
||||
@@ -613,27 +613,7 @@ llvm::DIType CGDebugInfo::getOrCreateTypeDeclaration(QualType PointeeTy,
|
||||
llvm::DIFile Unit) {
|
||||
if (DebugKind > CodeGenOptions::LimitedDebugInfo)
|
||||
return getOrCreateType(PointeeTy, Unit);
|
||||
|
||||
// Limit debug info for the pointee type.
|
||||
|
||||
// If we have an existing type, use that, it's still smaller than creating
|
||||
// a new type.
|
||||
llvm::DIType Ty = getTypeOrNull(PointeeTy);
|
||||
if (Ty.Verify()) return Ty;
|
||||
|
||||
// Handle qualifiers.
|
||||
if (PointeeTy.hasLocalQualifiers())
|
||||
return CreateQualifiedType(PointeeTy, Unit);
|
||||
|
||||
if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
|
||||
RecordDecl *RD = RTy->getDecl();
|
||||
llvm::DIDescriptor FDContext =
|
||||
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
||||
llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
|
||||
TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;
|
||||
return RetTy;
|
||||
}
|
||||
return getOrCreateType(PointeeTy, Unit);
|
||||
return getOrCreateType(PointeeTy, Unit, true);
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
|
||||
@@ -730,11 +710,12 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
|
||||
return BlockLiteralGeneric;
|
||||
}
|
||||
|
||||
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
|
||||
llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit,
|
||||
bool Declaration) {
|
||||
// Typedefs are derived from some other type. If we have a typedef of a
|
||||
// typedef, make sure to emit the whole chain.
|
||||
llvm::DIType Src =
|
||||
getOrCreateTypeDeclaration(Ty->getDecl()->getUnderlyingType(), Unit);
|
||||
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, Declaration);
|
||||
if (!Src.Verify())
|
||||
return llvm::DIType();
|
||||
// We don't set size information, but do specify where the typedef was
|
||||
@@ -1394,8 +1375,15 @@ llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
|
||||
}
|
||||
|
||||
/// CreateType - get structure or union type.
|
||||
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
||||
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) {
|
||||
RecordDecl *RD = Ty->getDecl();
|
||||
if (Declaration) {
|
||||
llvm::DIDescriptor FDContext =
|
||||
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
||||
llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
|
||||
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RetTy;
|
||||
return RetTy;
|
||||
}
|
||||
|
||||
// Get overall information about the record type for the debug info.
|
||||
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
|
||||
@@ -1908,7 +1896,7 @@ llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {
|
||||
|
||||
/// getOrCreateType - Get the type from the cache or create a new
|
||||
/// one if necessary.
|
||||
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
||||
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit, bool Declaration) {
|
||||
if (Ty.isNull())
|
||||
return llvm::DIType();
|
||||
|
||||
@@ -1921,7 +1909,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
|
||||
return T;
|
||||
|
||||
// Otherwise create the type.
|
||||
llvm::DIType Res = CreateTypeNode(Ty, Unit);
|
||||
llvm::DIType Res = CreateTypeNode(Ty, Unit, Declaration);
|
||||
void* TyPtr = Ty.getAsOpaquePtr();
|
||||
|
||||
// And update the type cache.
|
||||
@@ -1981,10 +1969,10 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
|
||||
}
|
||||
|
||||
/// CreateTypeNode - Create a new debug type node.
|
||||
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
|
||||
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit, bool Declaration) {
|
||||
// Handle qualifiers, which recursively handles what they refer to.
|
||||
if (Ty.hasLocalQualifiers())
|
||||
return CreateQualifiedType(Ty, Unit);
|
||||
return CreateQualifiedType(Ty, Unit, Declaration);
|
||||
|
||||
const char *Diag = 0;
|
||||
|
||||
@@ -2015,9 +2003,9 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
|
||||
case Type::BlockPointer:
|
||||
return CreateType(cast<BlockPointerType>(Ty), Unit);
|
||||
case Type::Typedef:
|
||||
return CreateType(cast<TypedefType>(Ty), Unit);
|
||||
return CreateType(cast<TypedefType>(Ty), Unit, Declaration);
|
||||
case Type::Record:
|
||||
return CreateType(cast<RecordType>(Ty));
|
||||
return CreateType(cast<RecordType>(Ty), Declaration);
|
||||
case Type::Enum:
|
||||
return CreateEnumType(cast<EnumType>(Ty)->getDecl());
|
||||
case Type::FunctionProto:
|
||||
@@ -2174,7 +2162,7 @@ llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
|
||||
case Type::Record:
|
||||
return CreateLimitedType(cast<RecordType>(Ty));
|
||||
default:
|
||||
return CreateTypeNode(Ty, Unit);
|
||||
return CreateTypeNode(Ty, Unit, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,14 +108,14 @@ class CGDebugInfo {
|
||||
unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl);
|
||||
llvm::DIType CreateType(const BuiltinType *Ty);
|
||||
llvm::DIType CreateType(const ComplexType *Ty);
|
||||
llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);
|
||||
llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);
|
||||
llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F, bool Declaration);
|
||||
llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F, bool Declaration);
|
||||
llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
|
||||
llvm::DIFile F);
|
||||
llvm::DIType CreateType(const PointerType *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 RecordType *Ty);
|
||||
llvm::DIType CreateType(const RecordType *Ty, bool Declaration);
|
||||
llvm::DIType CreateLimitedType(const RecordType *Ty);
|
||||
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
|
||||
llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
|
||||
@@ -326,14 +326,14 @@ private:
|
||||
|
||||
/// getOrCreateType - Get the type from the cache or create a new type if
|
||||
/// necessary.
|
||||
llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
|
||||
llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F, bool Declaration = false);
|
||||
|
||||
/// 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.
|
||||
llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
|
||||
llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F, bool Declaration);
|
||||
|
||||
/// getObjCInterfaceDecl - return the underlying ObjCInterfaceDecl
|
||||
/// if Ty is an ObjCInterface or a pointer to one.
|
||||
|
||||
@@ -76,3 +76,27 @@ incomplete (*x)[3];
|
||||
// CHECK: [[INCARRAY]] = {{.*}}metadata [[INCTYPE:![0-9]*]], metadata {{![0-9]*}}, i32 0, i32 0} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from incomplete]
|
||||
// CHECK: [[INCTYPE]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [fwd]
|
||||
}
|
||||
|
||||
namespace pr16214 {
|
||||
struct a {
|
||||
int i;
|
||||
};
|
||||
|
||||
typedef a at;
|
||||
|
||||
struct b {
|
||||
};
|
||||
|
||||
typedef b bt;
|
||||
|
||||
void func() {
|
||||
at a_inst;
|
||||
bt *b_ptr_inst;
|
||||
const bt *b_cnst_ptr_inst;
|
||||
}
|
||||
|
||||
// CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [a]
|
||||
// CHECK: [[A_MEM]] = metadata !{metadata [[A_I:![0-9]*]], metadata !{{[0-9]*}}}
|
||||
// CHECK: [[A_I]] = {{.*}} ; [ DW_TAG_member ] [i] {{.*}} [from int]
|
||||
// CHECK: ; [ DW_TAG_structure_type ] [b] {{.*}}[fwd]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user