forked from OSchip/llvm-project
[codeview] Emit nested enums and typedefs from classes
Previously we limited ourselves to only emitting nested classes, but we need other kinds of types as well. This fixes the Visual Studio STL visualizers, so that users can visualize std::string and other objects. llvm-svn: 310410
This commit is contained in:
parent
9f338dcd4f
commit
e2e82061f9
|
@ -1183,13 +1183,13 @@ void CGDebugInfo::CollectRecordNormalField(
|
|||
elements.push_back(FieldType);
|
||||
}
|
||||
|
||||
void CGDebugInfo::CollectRecordNestedRecord(
|
||||
const RecordDecl *RD, SmallVectorImpl<llvm::Metadata *> &elements) {
|
||||
QualType Ty = CGM.getContext().getTypeDeclType(RD);
|
||||
void CGDebugInfo::CollectRecordNestedType(
|
||||
const TypeDecl *TD, SmallVectorImpl<llvm::Metadata *> &elements) {
|
||||
QualType Ty = CGM.getContext().getTypeDeclType(TD);
|
||||
// Injected class names are not considered nested records.
|
||||
if (isa<InjectedClassNameType>(Ty))
|
||||
return;
|
||||
SourceLocation Loc = RD->getLocation();
|
||||
SourceLocation Loc = TD->getLocation();
|
||||
llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc));
|
||||
elements.push_back(nestedType);
|
||||
}
|
||||
|
@ -1205,9 +1205,9 @@ void CGDebugInfo::CollectRecordFields(
|
|||
else {
|
||||
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
|
||||
|
||||
// Debug info for nested records is included in the member list only for
|
||||
// Debug info for nested types is included in the member list only for
|
||||
// CodeView.
|
||||
bool IncludeNestedRecords = CGM.getCodeGenOpts().EmitCodeView;
|
||||
bool IncludeNestedTypes = CGM.getCodeGenOpts().EmitCodeView;
|
||||
|
||||
// Field number for non-static fields.
|
||||
unsigned fieldNo = 0;
|
||||
|
@ -1234,10 +1234,12 @@ void CGDebugInfo::CollectRecordFields(
|
|||
|
||||
// Bump field number for next field.
|
||||
++fieldNo;
|
||||
} else if (const auto *nestedRec = dyn_cast<CXXRecordDecl>(I))
|
||||
if (IncludeNestedRecords && !nestedRec->isImplicit() &&
|
||||
nestedRec->getDeclContext() == record)
|
||||
CollectRecordNestedRecord(nestedRec, elements);
|
||||
} else if (IncludeNestedTypes) {
|
||||
if (const auto *nestedType = dyn_cast<TypeDecl>(I))
|
||||
if (!nestedType->isImplicit() &&
|
||||
nestedType->getDeclContext() == record)
|
||||
CollectRecordNestedType(nestedType, elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -278,8 +278,8 @@ class CGDebugInfo {
|
|||
llvm::DIFile *F,
|
||||
SmallVectorImpl<llvm::Metadata *> &E,
|
||||
llvm::DIType *RecordTy, const RecordDecl *RD);
|
||||
void CollectRecordNestedRecord(const RecordDecl *RD,
|
||||
SmallVectorImpl<llvm::Metadata *> &E);
|
||||
void CollectRecordNestedType(const TypeDecl *RD,
|
||||
SmallVectorImpl<llvm::Metadata *> &E);
|
||||
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile *F,
|
||||
SmallVectorImpl<llvm::Metadata *> &E,
|
||||
llvm::DICompositeType *RecordTy);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
|
||||
|
||||
struct HasNested {
|
||||
enum InnerEnum { _BUF_SIZE = 1 };
|
||||
typedef int InnerTypedef;
|
||||
enum { InnerEnumerator = 2 };
|
||||
struct InnerStruct { };
|
||||
};
|
||||
HasNested f;
|
||||
|
||||
// CHECK: ![[INNERENUM:[0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "InnerEnum", {{.*}})
|
||||
// CHECK: ![[HASNESTED:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasNested",
|
||||
// CHECK-SAME: elements: ![[MEMBERS:[0-9]+]],
|
||||
//
|
||||
// CHECK: ![[MEMBERS]] = !{![[INNERENUM]], ![[INNERTYPEDEF:[0-9]+]], ![[UNNAMEDENUM:[0-9]+]], ![[INNERSTRUCT:[0-9]+]]}
|
||||
//
|
||||
// CHECK: ![[INNERTYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "InnerTypedef", scope: ![[HASNESTED]]{{.*}})
|
||||
//
|
||||
// CHECK: ![[UNNAMEDENUM]] = !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[HASNESTED]],
|
||||
// CHECK-SAME: elements: ![[UNNAMEDMEMBERS:[0-9]+]],
|
||||
// CHECK: ![[UNNAMEDMEMBERS]] = !{![[INNERENUMERATOR:[0-9]+]]}
|
||||
// CHECK: ![[INNERENUMERATOR]] = !DIEnumerator(name: "InnerEnumerator", value: 2)
|
||||
//
|
||||
// CHECK: ![[INNERSTRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "InnerStruct"
|
||||
// CHECK-SAME: flags: DIFlagFwdDecl
|
|
@ -1655,7 +1655,7 @@ struct llvm::ClassInfo {
|
|||
|
||||
TypeIndex VShapeTI;
|
||||
|
||||
std::vector<const DICompositeType *> NestedClasses;
|
||||
std::vector<const DIType *> NestedTypes;
|
||||
};
|
||||
|
||||
void CodeViewDebug::clear() {
|
||||
|
@ -1706,12 +1706,14 @@ ClassInfo CodeViewDebug::collectClassInfo(const DICompositeType *Ty) {
|
|||
} else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&
|
||||
DDTy->getName() == "__vtbl_ptr_type") {
|
||||
Info.VShapeTI = getTypeIndex(DDTy);
|
||||
} else if (DDTy->getTag() == dwarf::DW_TAG_typedef) {
|
||||
Info.NestedTypes.push_back(DDTy);
|
||||
} else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
|
||||
// Ignore friend members. It appears that MSVC emitted info about
|
||||
// friends in the past, but modern versions do not.
|
||||
}
|
||||
} else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
|
||||
Info.NestedClasses.push_back(Composite);
|
||||
Info.NestedTypes.push_back(Composite);
|
||||
}
|
||||
// Skip other unrecognized kinds of elements.
|
||||
}
|
||||
|
@ -1920,7 +1922,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
|
|||
}
|
||||
|
||||
// Create nested classes.
|
||||
for (const DICompositeType *Nested : Info.NestedClasses) {
|
||||
for (const DIType *Nested : Info.NestedTypes) {
|
||||
NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
|
||||
FLBR.writeMemberType(R);
|
||||
MemberCount++;
|
||||
|
@ -1928,7 +1930,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
|
|||
|
||||
TypeIndex FieldTI = FLBR.end(true);
|
||||
return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
|
||||
!Info.NestedClasses.empty());
|
||||
!Info.NestedTypes.empty());
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::getVBPTypeIndex() {
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
|
||||
|
||||
; C++ source to regenerate:
|
||||
; struct HasNested {
|
||||
; enum InnerEnum { _BUF_SIZE = 1 };
|
||||
; typedef int InnerTypedef;
|
||||
; enum { InnerEnumerator = 2 };
|
||||
; struct InnerStruct { };
|
||||
; };
|
||||
; HasNested f;
|
||||
; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
|
||||
|
||||
; ModuleID = 't.cpp'
|
||||
source_filename = "t.cpp"
|
||||
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-windows-msvc19.0.24215"
|
||||
|
||||
%struct.HasNested = type { i8 }
|
||||
|
||||
@"\01?f@@3UHasNested@@A" = global %struct.HasNested zeroinitializer, align 1, !dbg !0
|
||||
|
||||
!llvm.dbg.cu = !{!2}
|
||||
!llvm.module.flags = !{!17, !18, !19, !20}
|
||||
!llvm.ident = !{!21}
|
||||
|
||||
!0 = !DIGlobalVariableExpression(var: !1)
|
||||
!1 = distinct !DIGlobalVariable(name: "f", linkageName: "\01?f@@3UHasNested@@A", scope: !2, file: !3, line: 7, type: !6, isLocal: false, isDefinition: true)
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !16)
|
||||
!3 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "40c412b85e2b27acb30eef53983b1da4")
|
||||
!4 = !{!5, !10}
|
||||
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "InnerEnum", scope: !6, file: !3, line: 2, baseType: !9, size: 32, elements: !14, identifier: ".?AW4InnerEnum@HasNested@@")
|
||||
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasNested", file: !3, line: 1, size: 8, elements: !7, identifier: ".?AUHasNested@@")
|
||||
!7 = !{!5, !8, !10, !13}
|
||||
!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "InnerTypedef", scope: !6, file: !3, line: 3, baseType: !9)
|
||||
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!10 = !DICompositeType(tag: DW_TAG_enumeration_type, scope: !6, file: !3, line: 4, baseType: !9, size: 32, elements: !11, identifier: ".?AW4<unnamed-enum-InnerEnumerator>@HasNested@@")
|
||||
!11 = !{!12}
|
||||
!12 = !DIEnumerator(name: "InnerEnumerator", value: 2)
|
||||
!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "InnerStruct", scope: !6, file: !3, line: 5, flags: DIFlagFwdDecl, identifier: ".?AUInnerStruct@HasNested@@")
|
||||
!14 = !{!15}
|
||||
!15 = !DIEnumerator(name: "_BUF_SIZE", value: 1)
|
||||
!16 = !{!0}
|
||||
!17 = !{i32 2, !"CodeView", i32 1}
|
||||
!18 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!19 = !{i32 1, !"wchar_size", i32 2}
|
||||
!20 = !{i32 7, !"PIC Level", i32 2}
|
||||
!21 = !{!"clang version 6.0.0 "}
|
||||
|
||||
; InnerEnum:
|
||||
|
||||
; CHECK: FieldList ([[INNERENUM_MEMBERS:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
|
||||
; CHECK-NEXT: Enumerator {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
|
||||
; CHECK-NEXT: AccessSpecifier: Public (0x3)
|
||||
; CHECK-NEXT: EnumValue: 1
|
||||
; CHECK-NEXT: Name: _BUF_SIZE
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: }
|
||||
;
|
||||
; CHECK: Enum ([[INNERENUM:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_ENUM (0x1507)
|
||||
; CHECK-NEXT: NumEnumerators: 1
|
||||
; CHECK-NEXT: Properties [ (0x208)
|
||||
; CHECK-NEXT: HasUniqueName (0x200)
|
||||
; CHECK-NEXT: Nested (0x8)
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK-NEXT: UnderlyingType: int (0x74)
|
||||
; CHECK-NEXT: FieldListType: <field list> ([[INNERENUM_MEMBERS]])
|
||||
; CHECK-NEXT: Name: HasNested::InnerEnum
|
||||
; CHECK-NEXT: LinkageName: .?AW4InnerEnum@HasNested@@
|
||||
; CHECK-NEXT: }
|
||||
|
||||
; CHECK: FieldList ([[UNNAMED_MEMBERS:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
|
||||
; CHECK-NEXT: Enumerator {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
|
||||
; CHECK-NEXT: AccessSpecifier: Public (0x3)
|
||||
; CHECK-NEXT: EnumValue: 2
|
||||
; CHECK-NEXT: Name: InnerEnumerator
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: }
|
||||
;
|
||||
; CHECK: Enum ([[UNNAMEDENUM:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_ENUM (0x1507)
|
||||
; CHECK-NEXT: NumEnumerators: 1
|
||||
; CHECK-NEXT: Properties [ (0x208)
|
||||
; CHECK-NEXT: HasUniqueName (0x200)
|
||||
; CHECK-NEXT: Nested (0x8)
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK-NEXT: UnderlyingType: int (0x74)
|
||||
; CHECK-NEXT: FieldListType: <field list> ([[UNNAMED_MEMBERS]])
|
||||
; CHECK-NEXT: Name: HasNested::<unnamed-tag>
|
||||
; CHECK-NEXT: LinkageName: .?AW4<unnamed-enum-InnerEnumerator>@HasNested@@
|
||||
; CHECK-NEXT: }
|
||||
|
||||
; CHECK: Struct ([[INNERSTRUCT:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_STRUCTURE (0x1505)
|
||||
; CHECK-NEXT: MemberCount: 0
|
||||
; CHECK-NEXT: Properties [ (0x288)
|
||||
; CHECK-NEXT: ForwardReference (0x80)
|
||||
; CHECK-NEXT: HasUniqueName (0x200)
|
||||
; CHECK-NEXT: Nested (0x8)
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK-NEXT: FieldList: 0x0
|
||||
; CHECK-NEXT: DerivedFrom: 0x0
|
||||
; CHECK-NEXT: VShape: 0x0
|
||||
; CHECK-NEXT: SizeOf: 0
|
||||
; CHECK-NEXT: Name: HasNested::InnerStruct
|
||||
; CHECK-NEXT: LinkageName: .?AUInnerStruct@HasNested@@
|
||||
; CHECK-NEXT: }
|
||||
|
||||
; CHECK: FieldList ([[HASNESTED_MEMBERS:0x.*]]) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
|
||||
; CHECK-NEXT: NestedType {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_NESTTYPE (0x1510)
|
||||
; CHECK-NEXT: Type: HasNested::InnerEnum ([[INNERENUM]])
|
||||
; CHECK-NEXT: Name: InnerEnum
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: NestedType {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_NESTTYPE (0x1510)
|
||||
; CHECK-NEXT: Type: int (0x74)
|
||||
; CHECK-NEXT: Name: InnerTypedef
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: NestedType {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_NESTTYPE (0x1510)
|
||||
; CHECK-NEXT: Type: HasNested::<unnamed-tag> ([[UNNAMEDENUM]])
|
||||
; CHECK-NEXT: Name: {{$}}
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: NestedType {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_NESTTYPE (0x1510)
|
||||
; CHECK-NEXT: Type: HasNested::InnerStruct ([[INNERSTRUCT]])
|
||||
; CHECK-NEXT: Name: InnerStruct
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: }
|
||||
;
|
||||
; CHECK: Struct (0x1007) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_STRUCTURE (0x1505)
|
||||
; CHECK-NEXT: MemberCount: 4
|
||||
; CHECK-NEXT: Properties [ (0x210)
|
||||
; CHECK-NEXT: ContainsNestedClass (0x10)
|
||||
; CHECK-NEXT: HasUniqueName (0x200)
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK-NEXT: FieldList: <field list> ([[HASNESTED_MEMBERS]])
|
||||
; CHECK-NEXT: DerivedFrom: 0x0
|
||||
; CHECK-NEXT: VShape: 0x0
|
||||
; CHECK-NEXT: SizeOf: 1
|
||||
; CHECK-NEXT: Name: HasNested
|
||||
; CHECK-NEXT: LinkageName: .?AUHasNested@@
|
||||
; CHECK-NEXT: }
|
Loading…
Reference in New Issue