llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.85k stars 11.91k forks source link

"vtt" missing in SubroutineType #104765

Open mgschossmann opened 2 months ago

mgschossmann commented 2 months ago

When compiling following source, clang creates a virtual destructor for A with an artificial vtt argument. The DILocalVariable for vtt correctly has arg: 2. However, the field types of the DISubroutineType for this virtual destructor seems to miss the additional parameter, as it only has two members and thus represents a function with only one parameter.

Source:

struct B {
    virtual ~B() {}
};

struct A : virtual B {
};

A a;

LLVM-IR:

[...]
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 5, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !6, vtableHolder: !8, identifier: "_ZTS1A")
[...]
!34 = !DISubroutineType(types: !35)
!35 = !{null, !36}
!36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
[...]
!70 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", scope: !5, file: !3, line: 5, type: !34, scopeLine: 5, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !44, retainedNodes: !38)
!71 = !DILocalVariable(name: "this", arg: 1, scope: !70, type: !40, flags: DIFlagArtificial | DIFlagObjectPointer)
!72 = !DILocation(line: 0, scope: !70)
!73 = !DILocalVariable(name: "vtt", arg: 2, scope: !70, type: !74, flags: DIFlagArtificial)
!74 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !75, size: 64)
!75 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
[...]

I generated the IR using clang 19.1.0-rc2 on x86_64-unknown-linux-gnu. DWARF generated from this IR is not affected and includes all formal parameters.

The issue seems to be that in ItaniumCXXABI::addImplicitStructorParams, the parameter is added, but in CGDebugInfo::getOrCreateMethodType another type array is read to create the DISubroutineType.

https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/ItaniumCXXABI.cpp#L1870-L1890

https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/CGDebugInfo.cpp#L1938-L1946

llvmbot commented 2 months ago

@llvm/issue-subscribers-clang-codegen

Author: None (mgschossmann)

When compiling following source, clang creates a virtual destructor for `A` with an artificial `vtt` argument. The `DILocalVariable` for `vtt` correctly has `arg: 2`. However, the field `types` of the `DISubroutineType` for this virtual destructor seems to miss the additional parameter, as it only has two members and thus represents a function with only one parameter. Source: ``` C struct B { virtual ~B() {} }; struct A : virtual B { }; A a; ``` LLVM-IR: ``` llvm [...] !5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 5, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !6, vtableHolder: !8, identifier: "_ZTS1A") [...] !34 = !DISubroutineType(types: !35) !35 = !{null, !36} !36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) [...] !70 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", scope: !5, file: !3, line: 5, type: !34, scopeLine: 5, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !44, retainedNodes: !38) !71 = !DILocalVariable(name: "this", arg: 1, scope: !70, type: !40, flags: DIFlagArtificial | DIFlagObjectPointer) !72 = !DILocation(line: 0, scope: !70) !73 = !DILocalVariable(name: "vtt", arg: 2, scope: !70, type: !74, flags: DIFlagArtificial) !74 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !75, size: 64) !75 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) [...] ``` I generated the IR using clang 19.1.0-rc2 on `x86_64-unknown-linux-gnu`. DWARF generated from this IR is not affected and includes all formal parameters. The issue seems to be that in `ItaniumCXXABI::addImplicitStructorParams`, the parameter is added, but in `CGDebugInfo::getOrCreateMethodType` another type array is read to create the `DISubroutineType`. https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/ItaniumCXXABI.cpp#L1870-L1890 https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/CGDebugInfo.cpp#L1938-L1946
llvmbot commented 2 months ago

@llvm/issue-subscribers-debuginfo

Author: None (mgschossmann)

When compiling following source, clang creates a virtual destructor for `A` with an artificial `vtt` argument. The `DILocalVariable` for `vtt` correctly has `arg: 2`. However, the field `types` of the `DISubroutineType` for this virtual destructor seems to miss the additional parameter, as it only has two members and thus represents a function with only one parameter. Source: ``` C struct B { virtual ~B() {} }; struct A : virtual B { }; A a; ``` LLVM-IR: ``` llvm [...] !5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 5, size: 64, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !6, vtableHolder: !8, identifier: "_ZTS1A") [...] !34 = !DISubroutineType(types: !35) !35 = !{null, !36} !36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) [...] !70 = distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", scope: !5, file: !3, line: 5, type: !34, scopeLine: 5, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, declaration: !44, retainedNodes: !38) !71 = !DILocalVariable(name: "this", arg: 1, scope: !70, type: !40, flags: DIFlagArtificial | DIFlagObjectPointer) !72 = !DILocation(line: 0, scope: !70) !73 = !DILocalVariable(name: "vtt", arg: 2, scope: !70, type: !74, flags: DIFlagArtificial) !74 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !75, size: 64) !75 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) [...] ``` I generated the IR using clang 19.1.0-rc2 on `x86_64-unknown-linux-gnu`. DWARF generated from this IR is not affected and includes all formal parameters. The issue seems to be that in `ItaniumCXXABI::addImplicitStructorParams`, the parameter is added, but in `CGDebugInfo::getOrCreateMethodType` another type array is read to create the `DISubroutineType`. https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/ItaniumCXXABI.cpp#L1870-L1890 https://github.com/llvm/llvm-project/blob/d033ae172d1c5a85fd09c36e23608a9241ea2990/clang/lib/CodeGen/CGDebugInfo.cpp#L1938-L1946