DebugInfo: Don't allow type units to references types in the CU

We could only do this in limited ways (since we emit the TUs first, we
can't use ref_addr (& we can't use that in Split DWARF either) - so we
had to synthesize declarations into the TUs) and they were ambiguous in
some cases (if the CU type had internal linkage, parsing the TU would
require knowing which CU was referencing the TU to know which type the
declaration was for, which seems not-ideal). So to avoid all that, let's
just not reference types defined in the CU from TUs - instead moving the
TU type into the CU (recursively).

This does increase debug info size (by pulling more things out of type
units, into the compile unit) - about 2% of uncompressed dwp file size
for clang -O0 -g -gsplit-dwarf. (5% .debug_info.dwo section size
increase in the .dwp)
This commit is contained in:
David Blaikie 2022-03-25 22:42:41 +00:00
parent 16eaa5240e
commit a5032b2633
7 changed files with 154 additions and 174 deletions

View File

@ -333,3 +333,21 @@ void t8::mem() {
f1<t7>();
f1<decltype(&t8::mem)>();
}
namespace complex_type_units {
void external_function();
namespace {
struct internal_type;
}
template <void (*)() = external_function> struct t2;
template <typename = t2<>> class t3 {};
template <typename = internal_type, typename = t3<>>
struct t4 {
};
struct t5 {
t4<> v1;
};
void f1() {
t5 v1;
t3<> v2;
}
}

View File

@ -17,7 +17,7 @@
using namespace llvm;
unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) {
HasBeenUsed = true;
resetUsedFlag(true);
auto IterBool =
Pool.insert(std::make_pair(Sym, AddressPoolEntry(Pool.size(), TLS)));
return IterBool.first->second.Number;

View File

@ -3444,22 +3444,6 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
CU.addDIETypeSignature(RefDie, Signature);
}
DwarfDebug::NonTypeUnitContext::NonTypeUnitContext(DwarfDebug *DD)
: DD(DD),
TypeUnitsUnderConstruction(std::move(DD->TypeUnitsUnderConstruction)), AddrPoolUsed(DD->AddrPool.hasBeenUsed()) {
DD->TypeUnitsUnderConstruction.clear();
DD->AddrPool.resetUsedFlag();
}
DwarfDebug::NonTypeUnitContext::~NonTypeUnitContext() {
DD->TypeUnitsUnderConstruction = std::move(TypeUnitsUnderConstruction);
DD->AddrPool.resetUsedFlag(AddrPoolUsed);
}
DwarfDebug::NonTypeUnitContext DwarfDebug::enterNonTypeUnitContext() {
return NonTypeUnitContext(this);
}
// Add the Name along with its companion DIE to the appropriate accelerator
// table (for AccelTableKind::Dwarf it's always AccelDebugNames, for
// AccelTableKind::Apple, we use the table we got as an argument). If

View File

@ -665,19 +665,6 @@ public:
void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
DIE &Die, const DICompositeType *CTy);
class NonTypeUnitContext {
DwarfDebug *DD;
decltype(DwarfDebug::TypeUnitsUnderConstruction) TypeUnitsUnderConstruction;
bool AddrPoolUsed;
friend class DwarfDebug;
NonTypeUnitContext(DwarfDebug *DD);
public:
NonTypeUnitContext(NonTypeUnitContext&&) = default;
~NonTypeUnitContext();
};
NonTypeUnitContext enterNonTypeUnitContext();
/// Add a label so that arange data can be generated for it.
void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }

View File

@ -592,10 +592,8 @@ DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE,
// Skip updating the accelerator tables since this is not the full type.
if (MDString *TypeId = CTy->getRawIdentifier())
DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
else {
auto X = DD->enterNonTypeUnitContext();
else
finishNonUnitTypeDIE(TyDIE, CTy);
}
return &TyDIE;
}
constructTypeDIE(TyDIE, CTy);
@ -1843,11 +1841,5 @@ void DwarfUnit::addRnglistsBase() {
}
void DwarfTypeUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) {
addFlag(D, dwarf::DW_AT_declaration);
StringRef Name = CTy->getName();
if (!Name.empty())
addString(D, dwarf::DW_AT_name, Name);
if (Name.startswith("_STN") || !Name.contains('<'))
addTemplateParams(D, CTy->getTemplateParams());
getCU().createTypeDIE(CTy);
DD->getAddressPool().resetUsedFlag(true);
}

View File

@ -40,14 +40,14 @@
; CHECK: DW_AT_name ("t3")
; CHECK: DW_TAG_member
; CHECK: DW_AT_type {{.*}} "t2<&foo>"
; CHECK: DW_TAG_namespace
; CHECK: [[T1:0x[0-9a-f]*]]: DW_TAG_structure_type
; CHECK: DW_AT_name ("t1")
; CHECK: DW_TAG_structure_type
; CHECK: DW_AT_name ("t2<&foo>")
; CHECK: DW_TAG_member
; CHECK: DW_AT_name ("v1")
; CHECK: DW_AT_type ([[T1]] "(anonymous namespace)::t1")
; CHECK: DW_AT_type ([[T1:0x[0-9a-f]*]] "(anonymous namespace)::t1")
; CHECK: DW_TAG_namespace
; CHECK: [[T1]]: DW_TAG_structure_type
; CHECK: DW_AT_name ("t1")
; CHECK: .debug_types contents:

View File

@ -1,41 +1,18 @@
; RUN: llc -filetype=obj -O0 -generate-type-units -mtriple=x86_64-unknown-linux-gnu < %s \
; RUN: | llvm-dwarfdump -debug-info -debug-types - | FileCheck %s
; Test that a type unit referencing a non-type unit produces a declaration of
; the referent in the referee.
; This test was originally for testing references to non-TU types from TUs, but
; it's currently too complicated to get that right reliably - non-TU types may
; have local linkage so declaring them in a TU is unreliable (consumers would
; have to be context-dependent to know which CU the TU is referenced from to
; know which type definition to match the declaration in the TU up to)
; This test was intended to test this:
; * Also check that an attempt to reference an internal linkage (defined in an anonymous
; * namespace) type from a type unit (could happen with a pimpl idiom, for instance -
; * it does mean the linkage-having type can only be defined in one translation
; * unit anyway) forces the referent to not be placed in a type unit (because the
; * declaration of the internal linkage type would be ambiguous/wouldn't allow a
; * consumer to find the definition with certainty)
; But the implementation was buggy, so for now, it's reverted but still test covered.
; A buggy input/case looks like this:
; namespace {
; template <typename> struct a {};
; } // namespace
; class c {
; c();
; };
; class b {
; b();
; a<c> ax;
; };
; b::b() {}
; c::c() {}
; I haven't bothered adding a test case for this ^ to avoid regression, as
; likely we'll move in a different direction entirely, since this approach is
; incomplete anyway. Specifically it looks like we want a flag on DICompositeType
; to indicate whether it should go in a type unit - the current frontend strategy
; of omitting the 'identifier' field is inadequate (since it breaks LLVM IR linking
; type resolution - leaving a separate decl/def of the same type), so if we fix that
; we can fix the internal-referencing issue by using such a flag instead of trying
; to figure it out in the backend.
; Might as well keep the complex cases here in case we revisit this (with a flag
; on the type to indicate whether it should be in a type unit or not, distinct
; from the mangled name indicating whether the type has linkage or not perhaps
; (rather than checing the namespace scopes to see if any are internal (which
; doesn't handle the linkage of, say, a template instantiated with an internal
; type))
; Built from the following source, compiled with this command:
; $ clang++-tot decl.cpp -g -fdebug-types-section -c
@ -89,7 +66,7 @@
; };
; ref_templ_non_tu_simple v3;
;
; // Modify templ_non_tu<long>'s name to be mangled ('_STN' name '|' args)
; // Modify templ_non_tu<bool>'s name to be mangled ('_STN' name '|' args)
; template <>
; struct templ_non_tu<bool> {
; virtual void f1();
@ -102,59 +79,28 @@
; CHECK-LABEL: Type Unit:
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"tu_ref_non_tu"
; CHECK-LABEL: Type Unit:
; CHECK: DW_TAG_structure_type
; CHECK: DW_TAG_class_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_internal"
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_byte_size
; CHECK-LABEL: Type Unit:
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu"
; CHECK: DW_TAG_structure_type
; CHECK-NEXT: DW_AT_declaration (true)
; CHECK-NEXT: DW_AT_name ("templ_non_tu<int>")
; CHECK-LABEL: Type Unit:
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu_simple"
; CHECK: DW_TAG_structure_type
; CHECK-NEXT: DW_AT_declaration (true)
; CHECK-NEXT: DW_AT_name ("templ_non_tu")
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_template_type_parameter
; CHECK-NEXT: DW_AT_type {{.*}}"long"
; CHECK-LABEL: Type Unit:
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu_mangled"
; CHECK: DW_TAG_structure_type
; CHECK-NEXT: DW_AT_declaration (true)
; CHECK-NEXT: DW_AT_name ("_STNtempl_non_tu|<bool>")
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_template_type_parameter
; CHECK-NEXT: DW_AT_type {{.*}}"bool"
; CHECK: DW_AT_name {{.*}}"ref_from_ref_internal_template"
; CHECK-LABEL: Compile Unit:
; CHECK: DW_TAG_structure_type
; CHECK-NEXT: DW_AT_declaration (true)
; CHECK-NEXT: DW_AT_signature (0xb1cde890d320f5c2)
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"tu_ref_non_tu"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"non_tu"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_internal"
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_byte_size
; CHECK: DW_TAG_namespace
; CHECK-NOT: {{DW_TAG|DW_AT}}
@ -162,8 +108,48 @@
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"internal"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"internal_template<ref_from_ref_internal_template>"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"_STNtempl_non_tu|<int>"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu_simple"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name ("templ_non_tu")
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_template_type_parameter
; CHECK-NEXT: DW_AT_type {{.*}}"long"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_templ_non_tu_mangled"
; CHECK: DW_TAG_structure_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name ("_STNtempl_non_tu|<bool>")
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_template_type_parameter
; CHECK-NEXT: DW_AT_type {{.*}}"bool"
; CHECK: DW_TAG_class_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}}"ref_internal_template"
; CHECK: DW_TAG_class_type
; CHECK-NEXT: DW_AT_declaration (true)
; CHECK-NEXT: DW_AT_signature (0x30c4e2370930c7ad)
%struct.ref_internal = type { %"struct.(anonymous namespace)::internal" }
%"struct.(anonymous namespace)::internal" = type { i8 }
%class.ref_internal_template = type { %"struct.(anonymous namespace)::internal_template" }
%"struct.(anonymous namespace)::internal_template" = type { i8 }
%class.ref_from_ref_internal_template = type { i8 }
%struct.non_tu = type { i32 (...)** }
%struct.templ_non_tu = type { i32 (...)** }
%struct.templ_non_tu.0 = type { i32 (...)** }
@ -178,6 +164,8 @@
@v3 = dso_local global { { i8** } } { { i8** } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV12templ_non_tuIlE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !32
@_ZTV12templ_non_tuIbE = dso_local unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI12templ_non_tuIbE to i8*), i8* bitcast (void (%struct.templ_non_tu.1*)* @_ZN12templ_non_tuIbE2f1Ev to i8*)] }, align 8
@v4 = dso_local global { { i8** } } { { i8** } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV12templ_non_tuIbE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !46
@v6 = dso_local global %class.ref_internal_template zeroinitializer, align 1, !dbg !60
@v7 = dso_local global %class.ref_from_ref_internal_template zeroinitializer, align 1, !dbg !69
@_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8*
@_ZTS6non_tu = dso_local constant [8 x i8] c"6non_tu\00", align 1
@_ZTI6non_tu = dso_local constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_ZTS6non_tu, i32 0, i32 0) }, align 8
@ -189,60 +177,60 @@
@_ZTI12templ_non_tuIbE = dso_local constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([18 x i8], [18 x i8]* @_ZTS12templ_non_tuIbE, i32 0, i32 0) }, align 8
; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_ZN6non_tu2f1Ev(%struct.non_tu* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !76 {
define dso_local void @_ZN6non_tu2f1Ev(%struct.non_tu* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !87 {
entry:
%this.addr = alloca %struct.non_tu*, align 8
store %struct.non_tu* %this, %struct.non_tu** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.non_tu** %this.addr, metadata !77, metadata !DIExpression()), !dbg !79
call void @llvm.dbg.declare(metadata %struct.non_tu** %this.addr, metadata !88, metadata !DIExpression()), !dbg !90
%this1 = load %struct.non_tu*, %struct.non_tu** %this.addr, align 8
ret void, !dbg !80
ret void, !dbg !91
}
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_ZN12templ_non_tuIiE2f1Ev(%struct.templ_non_tu* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !81 {
define dso_local void @_ZN12templ_non_tuIiE2f1Ev(%struct.templ_non_tu* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !92 {
entry:
%this.addr = alloca %struct.templ_non_tu*, align 8
store %struct.templ_non_tu* %this, %struct.templ_non_tu** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.templ_non_tu** %this.addr, metadata !82, metadata !DIExpression()), !dbg !84
call void @llvm.dbg.declare(metadata %struct.templ_non_tu** %this.addr, metadata !93, metadata !DIExpression()), !dbg !95
%this1 = load %struct.templ_non_tu*, %struct.templ_non_tu** %this.addr, align 8
ret void, !dbg !85
ret void, !dbg !96
}
; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_ZN12templ_non_tuIlE2f1Ev(%struct.templ_non_tu.0* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !86 {
define dso_local void @_ZN12templ_non_tuIlE2f1Ev(%struct.templ_non_tu.0* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !97 {
entry:
%this.addr = alloca %struct.templ_non_tu.0*, align 8
store %struct.templ_non_tu.0* %this, %struct.templ_non_tu.0** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.templ_non_tu.0** %this.addr, metadata !87, metadata !DIExpression()), !dbg !89
call void @llvm.dbg.declare(metadata %struct.templ_non_tu.0** %this.addr, metadata !98, metadata !DIExpression()), !dbg !100
%this1 = load %struct.templ_non_tu.0*, %struct.templ_non_tu.0** %this.addr, align 8
ret void, !dbg !90
ret void, !dbg !101
}
; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_ZN12templ_non_tuIbE2f1Ev(%struct.templ_non_tu.1* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !91 {
define dso_local void @_ZN12templ_non_tuIbE2f1Ev(%struct.templ_non_tu.1* noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #0 align 2 !dbg !102 {
entry:
%this.addr = alloca %struct.templ_non_tu.1*, align 8
store %struct.templ_non_tu.1* %this, %struct.templ_non_tu.1** %this.addr, align 8
call void @llvm.dbg.declare(metadata %struct.templ_non_tu.1** %this.addr, metadata !92, metadata !DIExpression()), !dbg !94
call void @llvm.dbg.declare(metadata %struct.templ_non_tu.1** %this.addr, metadata !103, metadata !DIExpression()), !dbg !105
%this1 = load %struct.templ_non_tu.1*, %struct.templ_non_tu.1** %this.addr, align 8
ret void, !dbg !95
ret void, !dbg !106
}
attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!70, !71, !72, !73, !74}
!llvm.ident = !{!75}
!llvm.module.flags = !{!81, !82, !83, !84, !85}
!llvm.ident = !{!86}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "v1", scope: !2, file: !3, line: 8, type: !60, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 14.0.0 (git@github.com:llvm/llvm-project.git ab4756338c5b2216d52d9152b2f7e65f233c4dac)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
!3 = !DIFile(filename: "decl.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
!4 = !{!0, !5, !13, !32, !46}
!1 = distinct !DIGlobalVariable(name: "v1", scope: !2, file: !3, line: 8, type: !71, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0 (git@github.com:llvm/llvm-project.git 862896df6210f6660514f9f68051cd0371832f37)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
!3 = !DIFile(filename: "test.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch", checksumkind: CSK_MD5, checksum: "84728cc618f91cd3bdecda0aa2d09c2d")
!4 = !{!0, !5, !13, !32, !46, !60, !69}
!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
!6 = distinct !DIGlobalVariable(name: "v5", scope: !2, file: !3, line: 17, type: !7, isLocal: false, isDefinition: true)
!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ref_internal", file: !3, line: 14, size: 8, flags: DIFlagTypePassByValue, elements: !8, identifier: "_ZTS12ref_internal")
@ -256,7 +244,7 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ref_templ_non_tu", file: !3, line: 30, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !16, identifier: "_ZTS16ref_templ_non_tu")
!16 = !{!17}
!17 = !DIDerivedType(tag: DW_TAG_member, name: "v1", scope: !15, file: !3, line: 31, baseType: !18, size: 64)
!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "templ_non_tu<int>", file: !3, line: 26, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !19, vtableHolder: !18, templateParams: !30)
!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_STNtempl_non_tu|<int>", file: !3, line: 26, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !19, vtableHolder: !18, templateParams: !30)
!19 = !{!20, !26}
!20 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$templ_non_tu", scope: !3, file: !3, baseType: !21, size: 64, flags: DIFlagArtificial)
!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64)
@ -298,39 +286,50 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
!57 = !{!58}
!58 = !DITemplateTypeParameter(name: "T", type: !59)
!59 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
!60 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tu_ref_non_tu", file: !3, line: 5, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !61, identifier: "_ZTS13tu_ref_non_tu")
!61 = !{!62}
!62 = !DIDerivedType(tag: DW_TAG_member, name: "v1", scope: !60, file: !3, line: 6, baseType: !63, size: 64)
!63 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "non_tu", file: !3, line: 1, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !64, vtableHolder: !63)
!64 = !{!65, !66}
!65 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$non_tu", scope: !3, file: !3, baseType: !21, size: 64, flags: DIFlagArtificial)
!66 = !DISubprogram(name: "f1", linkageName: "_ZN6non_tu2f1Ev", scope: !63, file: !3, line: 2, type: !67, scopeLine: 2, containingType: !63, virtualIndex: 0, flags: DIFlagPrototyped, spFlags: DISPFlagVirtual)
!67 = !DISubroutineType(types: !68)
!68 = !{null, !69}
!69 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !63, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!70 = !{i32 7, !"Dwarf Version", i32 5}
!71 = !{i32 2, !"Debug Info Version", i32 3}
!72 = !{i32 1, !"wchar_size", i32 4}
!73 = !{i32 7, !"uwtable", i32 1}
!74 = !{i32 7, !"frame-pointer", i32 2}
!75 = !{!"clang version 14.0.0 (git@github.com:llvm/llvm-project.git ab4756338c5b2216d52d9152b2f7e65f233c4dac)"}
!76 = distinct !DISubprogram(name: "f1", linkageName: "_ZN6non_tu2f1Ev", scope: !63, file: !3, line: 4, type: !67, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !66, retainedNodes: !12)
!77 = !DILocalVariable(name: "this", arg: 1, scope: !76, type: !78, flags: DIFlagArtificial | DIFlagObjectPointer)
!78 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !63, size: 64)
!79 = !DILocation(line: 0, scope: !76)
!80 = !DILocation(line: 4, column: 20, scope: !76)
!81 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIiE2f1Ev", scope: !18, file: !3, line: 29, type: !27, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !26, retainedNodes: !12)
!82 = !DILocalVariable(name: "this", arg: 1, scope: !81, type: !83, flags: DIFlagArtificial | DIFlagObjectPointer)
!83 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
!84 = !DILocation(line: 0, scope: !81)
!85 = !DILocation(line: 29, column: 31, scope: !81)
!86 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIlE2f1Ev", scope: !37, file: !3, line: 41, type: !40, scopeLine: 41, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !39, retainedNodes: !12)
!87 = !DILocalVariable(name: "this", arg: 1, scope: !86, type: !88, flags: DIFlagArtificial | DIFlagObjectPointer)
!88 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !37, size: 64)
!89 = !DILocation(line: 0, scope: !86)
!90 = !DILocation(line: 41, column: 32, scope: !86)
!91 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIbE2f1Ev", scope: !51, file: !3, line: 52, type: !54, scopeLine: 52, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !53, retainedNodes: !12)
!92 = !DILocalVariable(name: "this", arg: 1, scope: !91, type: !93, flags: DIFlagArtificial | DIFlagObjectPointer)
!93 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !51, size: 64)
!94 = !DILocation(line: 0, scope: !91)
!95 = !DILocation(line: 52, column: 32, scope: !91)
!60 = !DIGlobalVariableExpression(var: !61, expr: !DIExpression())
!61 = distinct !DIGlobalVariable(name: "v6", scope: !2, file: !3, line: 66, type: !62, isLocal: false, isDefinition: true)
!62 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "ref_internal_template", file: !3, line: 63, size: 8, flags: DIFlagTypePassByValue, elements: !63, identifier: "_ZTS21ref_internal_template")
!63 = !{!64}
!64 = !DIDerivedType(tag: DW_TAG_member, name: "ax", scope: !62, file: !3, line: 64, baseType: !65, size: 8)
!65 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "internal_template<ref_from_ref_internal_template>", scope: !11, file: !3, line: 59, size: 8, flags: DIFlagTypePassByValue, elements: !12, templateParams: !66)
!66 = !{!67}
!67 = !DITemplateTypeParameter(type: !68)
!68 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "ref_from_ref_internal_template", file: !3, line: 61, size: 8, flags: DIFlagTypePassByValue, elements: !12, identifier: "_ZTS30ref_from_ref_internal_template")
!69 = !DIGlobalVariableExpression(var: !70, expr: !DIExpression())
!70 = distinct !DIGlobalVariable(name: "v7", scope: !2, file: !3, line: 67, type: !68, isLocal: false, isDefinition: true)
!71 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "tu_ref_non_tu", file: !3, line: 5, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !72, identifier: "_ZTS13tu_ref_non_tu")
!72 = !{!73}
!73 = !DIDerivedType(tag: DW_TAG_member, name: "v1", scope: !71, file: !3, line: 6, baseType: !74, size: 64)
!74 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "non_tu", file: !3, line: 1, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !75, vtableHolder: !74)
!75 = !{!76, !77}
!76 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$non_tu", scope: !3, file: !3, baseType: !21, size: 64, flags: DIFlagArtificial)
!77 = !DISubprogram(name: "f1", linkageName: "_ZN6non_tu2f1Ev", scope: !74, file: !3, line: 2, type: !78, scopeLine: 2, containingType: !74, virtualIndex: 0, flags: DIFlagPrototyped, spFlags: DISPFlagVirtual)
!78 = !DISubroutineType(types: !79)
!79 = !{null, !80}
!80 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !74, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!81 = !{i32 7, !"Dwarf Version", i32 5}
!82 = !{i32 2, !"Debug Info Version", i32 3}
!83 = !{i32 1, !"wchar_size", i32 4}
!84 = !{i32 7, !"uwtable", i32 2}
!85 = !{i32 7, !"frame-pointer", i32 2}
!86 = !{!"clang version 15.0.0 (git@github.com:llvm/llvm-project.git 862896df6210f6660514f9f68051cd0371832f37)"}
!87 = distinct !DISubprogram(name: "f1", linkageName: "_ZN6non_tu2f1Ev", scope: !74, file: !3, line: 4, type: !78, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !77, retainedNodes: !12)
!88 = !DILocalVariable(name: "this", arg: 1, scope: !87, type: !89, flags: DIFlagArtificial | DIFlagObjectPointer)
!89 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !74, size: 64)
!90 = !DILocation(line: 0, scope: !87)
!91 = !DILocation(line: 4, column: 20, scope: !87)
!92 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIiE2f1Ev", scope: !18, file: !3, line: 29, type: !27, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !26, retainedNodes: !12)
!93 = !DILocalVariable(name: "this", arg: 1, scope: !92, type: !94, flags: DIFlagArtificial | DIFlagObjectPointer)
!94 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
!95 = !DILocation(line: 0, scope: !92)
!96 = !DILocation(line: 29, column: 31, scope: !92)
!97 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIlE2f1Ev", scope: !37, file: !3, line: 41, type: !40, scopeLine: 41, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !39, retainedNodes: !12)
!98 = !DILocalVariable(name: "this", arg: 1, scope: !97, type: !99, flags: DIFlagArtificial | DIFlagObjectPointer)
!99 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !37, size: 64)
!100 = !DILocation(line: 0, scope: !97)
!101 = !DILocation(line: 41, column: 32, scope: !97)
!102 = distinct !DISubprogram(name: "f1", linkageName: "_ZN12templ_non_tuIbE2f1Ev", scope: !51, file: !3, line: 52, type: !54, scopeLine: 52, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !53, retainedNodes: !12)
!103 = !DILocalVariable(name: "this", arg: 1, scope: !102, type: !104, flags: DIFlagArtificial | DIFlagObjectPointer)
!104 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !51, size: 64)
!105 = !DILocation(line: 0, scope: !102)
!106 = !DILocation(line: 52, column: 32, scope: !102)