Skip to content

"vtt" missing in SubroutineType #104765

Open
@mgschossmann

Description

@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:

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.

void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
// Check if we need a VTT parameter as well.
if (NeedsVTTParameter(CGF.CurGD)) {
ASTContext &Context = getContext();
// FIXME: avoid the fake decl
LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
QualType Q = Context.getAddrSpaceQualType(Context.VoidPtrTy, AS);
QualType T = Context.getPointerType(Q);
auto *VTTDecl = ImplicitParamDecl::Create(
Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"),
T, ImplicitParamKind::CXXVTT);
Params.insert(Params.begin() + 1, VTTDecl);
getStructorImplicitParamDecl(CGF) = VTTDecl;
}
}

llvm::DISubroutineType *
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *Unit) {
const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
if (Method->isStatic())
return cast_or_null<llvm::DISubroutineType>(
getOrCreateType(QualType(Func, 0), Unit));
return getOrCreateInstanceMethodType(Method->getThisType(), Func, Unit);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:codegenIR generation bugs: mangling, exceptions, etc.debuginfo

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions