[codeview] Improve names of types in scopes and member function ids

We now include namespace scope info in LF_FUNC_ID records and we emit
LF_MFUNC_ID records for member functions as we should.

Class names are now fully qualified, which is what MSVC does.

Add a little bit of scaffolding to handle ThisAdjustment when it arrives
in DISubprogram.

llvm-svn: 273358
This commit is contained in:
Reid Kleckner 2016-06-22 01:32:56 +00:00
parent 46fb2b903e
commit 0c5d874bea
5 changed files with 275 additions and 66 deletions

View File

@ -123,6 +123,57 @@ CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
return *Site;
}
static const DISubprogram *getQualifiedNameComponents(
const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
const DISubprogram *ClosestSubprogram = nullptr;
while (Scope != nullptr) {
if (ClosestSubprogram == nullptr)
ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
StringRef ScopeName = Scope->getName();
if (!ScopeName.empty())
QualifiedNameComponents.push_back(ScopeName);
Scope = Scope->getScope().resolve();
}
return ClosestSubprogram;
}
static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
StringRef TypeName) {
std::string FullyQualifiedName;
for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
FullyQualifiedName.append(QualifiedNameComponent);
FullyQualifiedName.append("::");
}
FullyQualifiedName.append(TypeName);
return FullyQualifiedName;
}
static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
SmallVector<StringRef, 5> QualifiedNameComponents;
getQualifiedNameComponents(Scope, QualifiedNameComponents);
return getQualifiedName(QualifiedNameComponents, Name);
}
TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
// No scope means global scope and that uses the zero index.
if (!Scope || isa<DIFile>(Scope))
return TypeIndex();
assert(!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type");
// Check if we've already translated this scope.
auto I = TypeIndices.find({Scope, nullptr});
if (I != TypeIndices.end())
return I->second;
// Build the fully qualified name of the scope.
std::string ScopeName =
getFullyQualifiedName(Scope->getScope().resolve(), Scope->getName());
TypeIndex TI =
TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName));
return recordTypeIndexForDINode(Scope, TI);
}
TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
// It's possible to ask for the FuncId of a function which doesn't have a
// subprogram: inlining a function with debug info into a function with none.
@ -134,22 +185,51 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
if (I != TypeIndices.end())
return I->second;
TypeIndex ParentScope = TypeIndex(0);
// The display name includes function template arguments. Drop them to match
// MSVC.
StringRef DisplayName = SP->getDisplayName().split('<').first;
FuncIdRecord FuncId(ParentScope, lowerSubprogramType(SP), DisplayName);
TypeIndex TI = TypeTable.writeFuncId(FuncId);
recordTypeIndexForDINode(SP, TI);
return TI;
const DIScope *Scope = SP->getScope().resolve();
TypeIndex TI;
if (const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
// If the scope is a DICompositeType, then this must be a method. Member
// function types take some special handling, and require access to the
// subprogram.
TypeIndex ClassType = getTypeIndex(Class);
MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
DisplayName);
TI = TypeTable.writeMemberFuncId(MFuncId);
} else {
// Otherwise, this must be a free function.
TypeIndex ParentScope = getScopeIndex(Scope);
FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
TI = TypeTable.writeFuncId(FuncId);
}
return recordTypeIndexForDINode(SP, TI);
}
void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
const DICompositeType *Class) {
// Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide
// with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}.
auto I = TypeIndices.find({SP, nullptr});
if (I != TypeIndices.end())
return I->second;
// FIXME: Get the ThisAdjustment off of SP when it is available.
TypeIndex TI =
lowerTypeMemberFunction(SP->getType(), Class, /*ThisAdjustment=*/0);
return recordTypeIndexForDINode(SP, TI, Class);
}
TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
const DIType *ClassTy) {
auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
(void)InsertResult;
assert(InsertResult.second && "DINode was already assigned a type index");
return TI;
}
unsigned CodeViewDebug::getPointerSizeInBytes() {
@ -458,31 +538,6 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
emitCodeViewMagicVersion();
}
static const DISubprogram *getQualifiedNameComponents(
const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
const DISubprogram *ClosestSubprogram = nullptr;
while (Scope != nullptr) {
if (ClosestSubprogram == nullptr)
ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
StringRef ScopeName = Scope->getName();
if (!ScopeName.empty())
QualifiedNameComponents.push_back(ScopeName);
Scope = Scope->getScope().resolve();
}
return ClosestSubprogram;
}
static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
StringRef TypeName) {
std::string FullyQualifiedName;
for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
FullyQualifiedName.append(QualifiedNameComponent);
FullyQualifiedName.append("::");
}
FullyQualifiedName.append(TypeName);
return FullyQualifiedName;
}
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
// For each function there is a separate subsection
@ -499,12 +554,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
// If we have a display name, build the fully qualified name by walking the
// chain of scopes.
if (SP != nullptr && !SP->getDisplayName().empty()) {
SmallVector<StringRef, 5> QualifiedNameComponents;
getQualifiedNameComponents(SP->getScope().resolve(),
QualifiedNameComponents);
FuncName = getQualifiedName(QualifiedNameComponents, SP->getDisplayName());
}
if (SP != nullptr && !SP->getDisplayName().empty())
FuncName =
getFullyQualifiedName(SP->getScope().resolve(), SP->getDisplayName());
// If our DISubprogram name is empty, use the mangled name.
if (FuncName.empty())
@ -792,8 +844,12 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
case dwarf::DW_TAG_volatile_type:
return lowerTypeModifier(cast<DIDerivedType>(Ty));
case dwarf::DW_TAG_subroutine_type:
if (ClassTy)
return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy);
if (ClassTy) {
// The member function type of a member function pointer has no
// ThisAdjustment.
return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
/*ThisAdjustment=*/0);
}
return lowerTypeFunction(cast<DISubroutineType>(Ty));
case dwarf::DW_TAG_enumeration_type:
return lowerTypeEnum(cast<DICompositeType>(Ty));
@ -1113,7 +1169,8 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
}
TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
const DIType *ClassTy) {
const DIType *ClassTy,
int ThisAdjustment) {
// Lower the containing class type.
TypeIndex ClassType = getTypeIndex(ClassTy);
@ -1150,14 +1207,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
// ThisPointerAdjustment.
TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
ArgTypeIndices.size(), ArgListIndex, 0));
return TI;
}
TypeIndex CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) {
auto ClassType = dyn_cast_or_null<DIType>(SP->getScope().resolve());
TypeIndex TI = getTypeIndex(SP->getType(), ClassType);
ArgTypeIndices.size(), ArgListIndex, ThisAdjustment));
return TI;
}
@ -1243,7 +1293,10 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
FTI = TypeTable.writeFieldList(Fields);
}
return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, Ty->getName(),
std::string FullName =
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName,
Ty->getIdentifier(),
getTypeIndex(Ty->getBaseType())));
}
@ -1353,9 +1406,11 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
TypeRecordKind Kind = getRecordKind(Ty);
ClassOptions CO =
ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
std::string FullName =
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
TypeIndex(), TypeIndex(), 0, Ty->getName(), Ty->getIdentifier()));
TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier()));
return FwdDeclTI;
}
@ -1369,19 +1424,24 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
unsigned FieldCount;
std::tie(FieldTI, VShapeTI, FieldCount) = lowerRecordFieldList(Ty);
std::string FullName =
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
return TypeTable.writeClass(ClassRecord(
Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
TypeIndex(), VShapeTI, SizeInBytes, Ty->getName(), Ty->getIdentifier()));
TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier()));
// FIXME: Make an LF_UDT_SRC_LINE record.
}
TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
ClassOptions CO =
ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
std::string FullName =
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
TypeIndex FwdDeclTI =
TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
Ty->getName(), Ty->getIdentifier()));
FullName, Ty->getIdentifier()));
return FwdDeclTI;
}
@ -1391,8 +1451,10 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
unsigned FieldCount;
std::tie(FieldTI, std::ignore, FieldCount) = lowerRecordFieldList(Ty);
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
std::string FullName =
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None,
FieldTI, SizeInBytes, Ty->getName(),
FieldTI, SizeInBytes, FullName,
Ty->getIdentifier()));
// FIXME: Make an LF_UDT_SRC_LINE record.
}
@ -1484,8 +1546,7 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
TypeIndex TI = lowerType(Ty, ClassTy);
recordTypeIndexForDINode(Ty, TI, ClassTy);
return TI;
return recordTypeIndexForDINode(Ty, TI, ClassTy);
}
TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {

View File

@ -218,6 +218,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
DITypeRef ClassTyRef = DITypeRef());
codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
const DICompositeType *Class);
codeview::TypeIndex getScopeIndex(const DIScope *Scope);
codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
@ -227,7 +232,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty,
const DIType *ClassTy);
const DIType *ClassTy,
int ThisAdjustment);
codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
@ -242,8 +248,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
codeview::TypeIndex lowerSubprogramType(const DISubprogram *SP);
void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy);
ClassInfo &collectClassInfo(const DICompositeType *Ty);
@ -254,8 +258,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
lowerRecordFieldList(const DICompositeType *Ty);
/// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates.
void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI,
const DIType *ClassTy = nullptr);
codeview::TypeIndex recordTypeIndexForDINode(const DINode *Node,
codeview::TypeIndex TI,
const DIType *ClassTy = nullptr);
unsigned getPointerSizeInBytes();

View File

@ -0,0 +1,143 @@
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
; Check that we keep namespace scopes around the same way MSVC does.
; We do function scopes slightly differently, but everything should be alright.
; C++ source to regenerate:
; namespace foo {
; namespace bar {
; void baz() {
; struct LocalRecord {
; int x;
; } l;
; };
; struct GlobalRecord {
; int x;
; void method();
; } g;
; void GlobalRecord::method() {}
; }
; }
; CHECK-LABEL: FuncId ({{.*}}) {
; CHECK-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601)
; CHECK-NEXT: ParentScope: foo::bar ({{.*}})
; CHECK-NEXT: FunctionType: void () ({{.*}})
; CHECK-NEXT: Name: baz
; CHECK-NEXT: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 0
; CHECK: Properties [ (0x80)
; CHECK: ForwardReference (0x80)
; CHECK: ]
; CHECK: FieldList: 0x0
; CHECK: DerivedFrom: 0x0
; CHECK: VShape: 0x0
; CHECK: SizeOf: 0
; CHECK: Name: foo::bar::baz::LocalRecord
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 1
; CHECK: Properties [ (0x0)
; CHECK: ]
; CHECK: Name: foo::bar::baz::LocalRecord
; CHECK: }
; CHECK: Struct ({{.*}}) {
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
; CHECK: MemberCount: 0
; CHECK: Properties [ (0x280)
; CHECK: ForwardReference (0x80)
; CHECK: HasUniqueName (0x200)
; CHECK: ]
; CHECK: FieldList: 0x0
; CHECK: DerivedFrom: 0x0
; CHECK: VShape: 0x0
; CHECK: SizeOf: 0
; CHECK: Name: foo::bar::GlobalRecord
; CHECK: }
; CHECK-LABEL: MemberFuncId ({{.*}}) {
; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602)
; CHECK-NEXT: ClassType: foo::bar::GlobalRecord ({{.*}})
; CHECK-NEXT: FunctionType: void foo::bar::GlobalRecord::() ({{.*}})
; CHECK-NEXT: Name: method
; CHECK-NEXT: }
; 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.23918"
%"struct.foo::bar::GlobalRecord" = type { i32 }
%struct.LocalRecord = type { i32 }
@"\01?g@bar@foo@@3UGlobalRecord@12@A" = global %"struct.foo::bar::GlobalRecord" zeroinitializer, align 4
; Function Attrs: nounwind uwtable
define void @"\01?baz@bar@foo@@YAXXZ"() #0 !dbg !19 {
entry:
%l = alloca %struct.LocalRecord, align 4
call void @llvm.dbg.declare(metadata %struct.LocalRecord* %l, metadata !22, metadata !26), !dbg !27
ret void, !dbg !28
}
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: nounwind uwtable
define void @"\01?method@GlobalRecord@bar@foo@@QEAAXXZ"(%"struct.foo::bar::GlobalRecord"* %this) #0 align 2 !dbg !29 {
entry:
%this.addr = alloca %"struct.foo::bar::GlobalRecord"*, align 8
store %"struct.foo::bar::GlobalRecord"* %this, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8
call void @llvm.dbg.declare(metadata %"struct.foo::bar::GlobalRecord"** %this.addr, metadata !30, metadata !26), !dbg !32
%this1 = load %"struct.foo::bar::GlobalRecord"*, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8
ret void, !dbg !33
}
attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!15, !16, !17}
!llvm.ident = !{!18}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
!2 = !{}
!3 = !{!4}
!4 = distinct !DIGlobalVariable(name: "g", linkageName: "\01?g@bar@foo@@3UGlobalRecord@12@A", scope: !5, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, variable: %"struct.foo::bar::GlobalRecord"* @"\01?g@bar@foo@@3UGlobalRecord@12@A")
!5 = !DINamespace(name: "bar", scope: !6, file: !1, line: 2)
!6 = !DINamespace(name: "foo", scope: null, file: !1, line: 1)
!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "GlobalRecord", scope: !5, file: !1, line: 9, size: 32, align: 32, elements: !8, identifier: ".?AUGlobalRecord@bar@foo@@")
!8 = !{!9, !11}
!9 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !7, file: !1, line: 10, baseType: !10, size: 32, align: 32)
!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 11, type: !12, isLocal: false, isDefinition: false, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false)
!12 = !DISubroutineType(types: !13)
!13 = !{null, !14}
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!15 = !{i32 2, !"CodeView", i32 1}
!16 = !{i32 2, !"Debug Info Version", i32 3}
!17 = !{i32 1, !"PIC Level", i32 2}
!18 = !{!"clang version 3.9.0 "}
!19 = distinct !DISubprogram(name: "baz", linkageName: "\01?baz@bar@foo@@YAXXZ", scope: !5, file: !1, line: 3, type: !20, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!20 = !DISubroutineType(types: !21)
!21 = !{null}
!22 = !DILocalVariable(name: "l", scope: !19, file: !1, line: 6, type: !23)
!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "LocalRecord", scope: !19, file: !1, line: 4, size: 32, align: 32, elements: !24)
!24 = !{!25}
!25 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !23, file: !1, line: 5, baseType: !10, size: 32, align: 32)
!26 = !DIExpression()
!27 = !DILocation(line: 6, column: 5, scope: !19)
!28 = !DILocation(line: 7, column: 1, scope: !19)
!29 = distinct !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 13, type: !12, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !11, variables: !2)
!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64)
!32 = !DILocation(line: 0, scope: !29)
!33 = !DILocation(line: 13, column: 30, scope: !29)

View File

@ -56,8 +56,8 @@
; CHECK: ArgListType: () (0x1002)
; CHECK: }
; CHECK: FuncId (0x1004) {
; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
; CHECK: ParentScope: 0x0
; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602)
; CHECK: ClassType: A (0x1000)
; CHECK: FunctionType: void A::() (0x1003)
; CHECK: Name: A::thiscallcc
; CHECK: }

View File

@ -288,7 +288,7 @@
; CHECK: DerivedFrom: 0x0
; CHECK: VShape: 0x0
; CHECK: SizeOf: 0
; CHECK: Name: Nested
; CHECK: Name: Class::Nested
; CHECK: LinkageName: .?AUNested@Class@@
; CHECK: }
; CHECK: FieldList (0x1014) {
@ -310,7 +310,7 @@
; CHECK: DerivedFrom: 0x0
; CHECK: VShape: 0x0
; CHECK: SizeOf: 4
; CHECK: Name: Nested
; CHECK: Name: Class::Nested
; CHECK: LinkageName: .?AUNested@Class@@
; CHECK: }
; CHECK: Pointer (0x1016) {
@ -337,8 +337,8 @@
; CHECK: ThisAdjustment: 0
; CHECK: }
; CHECK: FuncId (0x1018) {
; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
; CHECK: ParentScope: 0x0
; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602)
; CHECK: ClassType: DerivedClass (0x100D)
; CHECK: FunctionType: void DerivedClass::() (0x1017)
; CHECK: Name: DerivedClass::DerivedClass
; CHECK: }