[clang] [llvm] Add support for template as type parameter (PR #127654)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 6 07:55:54 PST 2025
https://github.com/ykhatav updated https://github.com/llvm/llvm-project/pull/127654
>From 2714184615ef06027941c7bccee3a2453d76c24b Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 06:44:49 -0800
Subject: [PATCH 1/9] Support template as type
---
clang/include/clang/Basic/CodeGenOptions.def | 1 +
clang/include/clang/Driver/Options.td | 5 +
clang/lib/CodeGen/CGDebugInfo.cpp | 19 ++-
clang/lib/CodeGen/CGDebugInfo.h | 2 +
.../debug-info-temp-param-as-type.cpp | 52 ++++++++
llvm/include/llvm/IR/DIBuilder.h | 6 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 2 +
llvm/lib/IR/DIBuilder.cpp | 8 ++
llvm/lib/IR/Verifier.cpp | 8 +-
.../DebugInfo/X86/template-as-type-param.ll | 124 ++++++++++++++++++
10 files changed, 222 insertions(+), 5 deletions(-)
create mode 100644 clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
create mode 100644 llvm/test/DebugInfo/X86/template-as-type-param.ll
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 386652d2efa9e..79c3df2e43eef 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -468,6 +468,7 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
/// Enables emitting Import Call sections on supported targets that can be used
/// by the Windows kernel to enable import call optimization.
CODEGENOPT(ImportCallOptimization, 1, 0)
+CODEGENOPT(DebugTemplateParameterAsType, 1, 0)
/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d8123cc39fdc9..32a88d42dde49 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -9028,3 +9028,8 @@ def wasm_opt : Flag<["--"], "wasm-opt">,
Group<m_Group>,
HelpText<"Enable the wasm-opt optimizer (default)">,
MarshallingInfoNegativeFlag<LangOpts<"NoWasmOpt">>;
+defm debug_template_parameter_as_type
+ : BoolFOption<"debug-template-parameter-as-type",
+ CodeGenOpts<"DebugTemplateParameterAsType">,
+ DefaultFalse, PosFlag<SetTrue>, NegFlag<SetFalse>,
+ BothFlags<[], [CC1Option]>>;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index db595796c067e..d464a629443a4 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1003,6 +1003,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return DBuilder.createBasicType(BTName, Size, Encoding);
}
+llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
+ llvm::DIFile *U) {
+ llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
+ return DBuilder.createTemplateTypeParameterAsType(
+ U, Ty->getReplacedParameter()->getName(), debugType);
+}
+
llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt";
@@ -3611,7 +3618,8 @@ llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
/*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
}
-static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
+static QualType UnwrapTypeForDebugInfo(QualType T, const CodeGenModule &CGM) {
+ const ASTContext &C = CGM.getContext();
Qualifiers Quals;
do {
Qualifiers InnerQuals = T.getLocalQualifiers();
@@ -3664,6 +3672,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<MacroQualifiedType>(T)->getUnderlyingType();
break;
case Type::SubstTemplateTypeParm:
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ return C.getQualifiedType(T.getTypePtr(), Quals);
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
case Type::Auto:
@@ -3690,7 +3700,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
}
llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
- assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM.getContext()));
+ assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM));
auto It = TypeCache.find(Ty.getAsOpaquePtr());
if (It != TypeCache.end()) {
// Verify that the debug info still exists.
@@ -3729,7 +3739,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
});
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM);
if (auto *T = getTypeOrNull(Ty))
return T;
@@ -3866,6 +3876,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Decltype:
case Type::PackIndexing:
case Type::UnaryTransform:
+ if (Ty->getTypeClass() == Type::SubstTemplateTypeParm &&
+ CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ return CreateType(cast<SubstTemplateTypeParmType>(Ty), Unit);
break;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 38f73eca561b7..5e28fd5bf9039 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -228,6 +228,8 @@ class CGDebugInfo {
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const SubstTemplateTypeParmType *Ty,
+ llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
diff --git a/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
new file mode 100644
index 0000000000000..3422ce8f1e2bd
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -fdebug-template-parameter-as-type -triple x86_64-apple-darwin %s -o - | FileCheck %s
+
+
+template <typename T>
+struct TClass {
+ TClass();
+ void foo();
+ T val_;
+ int val2_;
+};
+
+template <typename T>
+void TClass<T>::foo() {
+ T tVar = 1;
+ T* pT = &tVar;
+ tVar++;
+}
+
+template <typename T>
+T bar(T tp) {
+ return tp;
+}
+
+int main () {
+ TClass<int> a;
+ a.val2_ = 3;
+ a.foo();
+ auto A = bar(42);
+ TClass<double> b;
+ return 0;
+}
+
+// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<int>"
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM:![0-9]+]]
+// CHECK: [[TPARAM]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val2_",{{.*}}baseType: [[INT]]
+
+// CHECK: !DILocalVariable(name: "A",{{.*}}type: [[TPARAM]])
+
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<double>"
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM2:![0-9]+]]
+// CHECK: [[TPARAM2]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[DOUBLE:![0-9]+]])
+// CHECK: [[DOUBLE]] = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
+
+// CHECK: distinct !DISubprogram(name: "foo"
+// CHECK: !DILocalVariable(name: "tVar",{{.*}}type: [[TPARAM]])
+// CHECK: !DILocalVariable(name: "pT",{{.*}}type: [[TPTR:![0-9]+]]
+// CHECK: [[TPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[TPARAM]]
+
+// CHECK: distinct !DISubprogram(name: "bar<int>"
+// CHECK: !DILocalVariable(name: "tp",{{.*}}type: [[TPARAM]])
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 6c479415b9ed2..342b6d94c71f7 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -550,6 +550,12 @@ namespace llvm {
StringRef Name,
DIType *Ty,
bool IsDefault);
+ /// \param Scope Scope in which this type is defined.
+ /// \param Name Type parameter name.
+ /// \param Ty Parameter type.
+ DIDerivedType *createTemplateTypeParameterAsType(DIScope *Scope,
+ StringRef Name,
+ DIType *Ty);
/// Create debugging information for template
/// value parameter.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0a8a1ad38c959..8557d833dfb0e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -520,6 +520,8 @@ void DwarfUnit::addTemplateParams(DIE &Buffer, DINodeArray TParams) {
constructTemplateTypeParameterDIE(Buffer, TTP);
else if (auto *TVP = dyn_cast<DITemplateValueParameter>(Element))
constructTemplateValueParameterDIE(Buffer, TVP);
+ else if (auto *TDT = dyn_cast<DIDerivedType>(Element))
+ createTypeDIE(TDT->getScope(), Buffer, TDT);
}
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 8f9462ab46d88..8dc5677459bac 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -458,6 +458,14 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
SetterName, PropertyAttributes, Ty);
}
+DIDerivedType *DIBuilder::createTemplateTypeParameterAsType(DIScope *Context,
+ StringRef Name,
+ DIType *Ty) {
+ return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_type_parameter,
+ Name, nullptr, 0, Context, Ty, 0, 0, 0, std::nullopt,
+ std::nullopt, DINode::FlagZero, nullptr);
+}
+
DITemplateTypeParameter *
DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,
DIType *Ty, bool isDefault) {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8432779c107de..c7435a629e23a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1241,6 +1241,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type ||
+ N.getTag() == dwarf::DW_TAG_template_type_parameter ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
@@ -1288,8 +1289,11 @@ void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
CheckDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
- CheckDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",
- &N, Params, Op);
+ CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
+ ((isa<DIDerivedType>(Op)) &&
+ (dyn_cast<DIDerivedType>(Op)->getTag() ==
+ dwarf::DW_TAG_template_type_parameter)),
+ "invalid template parameter", &N, Params, Op);
}
}
diff --git a/llvm/test/DebugInfo/X86/template-as-type-param.ll b/llvm/test/DebugInfo/X86/template-as-type-param.ll
new file mode 100644
index 0000000000000..b237a6630ee7b
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/template-as-type-param.ll
@@ -0,0 +1,124 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o %t -filetype=obj
+; RUN:llvm-dwarfdump %t | FileCheck %s
+;Source code for the IR below:
+;template <typename T>
+;struct A
+;{
+; A () : val_ (), val2_ () { }
+; T val_;
+; int val2_;
+;};
+
+;int main (void)
+;{
+; A<int> a;
+; a.val2_ = 3;
+; return 0;
+;}
+
+;CHECK: DW_TAG_structure_type
+;CHECK: DW_AT_name ("A<int>")
+;CHECK-NEXT: DW_AT_byte_size (0x08)
+;CHECK-NEXT: DW_AT_decl_file ("/path/to{{/|\\}}test.cpp")
+;CHECK-NEXT: DW_AT_decl_line (2)
+
+;CHECK-NOT: NULL
+
+;CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
+;CHECK-NEXT: DW_AT_type {{.*}} "int"
+;CHECK-NEXT: DW_AT_name ("T")
+
+;CHECK: DW_TAG_member
+;CHECK-NEXT: DW_AT_name ("val_")
+;CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
+
+;CHECK: DW_TAG_member
+;CHECK-NEXT: DW_AT_name ("val2_")
+;CHECK-NEXT: DW_AT_type {{.*}} "int"
+
+
+; ModuleID = '<stdin>'
+source_filename = "test.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.A = type { i32, i32 }
+
+$_ZN1AIiEC2Ev = comdat any
+
+; Function Attrs: mustprogress noinline norecurse optnone uwtable
+define dso_local noundef i32 @main() #0 !dbg !20 {
+entry:
+ %retval = alloca i32, align 4
+ %a = alloca %struct.A, align 4
+ store i32 0, i32* %retval, align 4
+ call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !24, metadata !DIExpression()), !dbg !25
+ call void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %a), !dbg !25
+ %val2_ = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 1, !dbg !26
+ store i32 3, i32* %val2_, align 4, !dbg !27
+ ret i32 0, !dbg !28
+}
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define linkonce_odr dso_local void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 !dbg !29 {
+
+entry:
+ %this.addr = alloca %struct.A*, align 8
+ store %struct.A* %this, %struct.A** %this.addr, align 8
+ call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !30, metadata !DIExpression()), !dbg !32
+ %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+ %val_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 0, !dbg !33
+ store i32 0, i32* %val_, align 4, !dbg !33
+ %val2_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 1, !dbg !34
+ store i32 0, i32* %val2_, align 4, !dbg !34
+ ret void, !dbg !35
+}
+
+attributes #0 = { mustprogress noinline norecurse 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 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
+attributes #2 = { 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" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!14, !15, !16, !17, !18}
+!llvm.ident = !{!19}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "", isOptimized: false, flags: " -S -g -O0 -emit-llvm reproducer.cxx -o reproducer.ll", runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "/path/to")
+!2 = !{!3}
+!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A<int>", file: !1, line: 2, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !4, templateParams: !12, identifier: "_ZTS1AIiE")
+!4 = !{!5, !7, !8}
+!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 5, baseType: !36, size: 32,offset: 32)
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 6, baseType: !6, size: 32, offset: 32)
+!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: 0)
+!9 = !DISubroutineType(types: !10)
+!10 = !{null, !11}
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!12 = !{!36}
+!13 = !DITemplateTypeParameter(name: "T", type: !6)
+!14 = !{i32 7, !"Dwarf Version", i32 4}
+!15 = !{i32 2, !"Debug Info Version", i32 3}
+!16 = !{i32 1, !"wchar_size", i32 4}
+!17 = !{i32 7, !"uwtable", i32 2}
+!18 = !{i32 7, !"frame-pointer", i32 2}
+!19 = !{!""}
+!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 10, type: !21, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !23)
+!21 = !DISubroutineType(types: !22)
+!22 = !{!6}
+!23 = !{}
+!24 = !DILocalVariable(name: "a", scope: !20, file: !1, line: 12, type: !3)
+!25 = !DILocation(line: 12, column: 10, scope: !20)
+!26 = !DILocation(line: 13, column: 5, scope: !20)
+!27 = !DILocation(line: 13, column: 11, scope: !20)
+!28 = !DILocation(line: 15, column: 3, scope: !20)
+!29 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !23)
+!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
+!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
+!32 = !DILocation(line: 0, scope: !29)
+!33 = !DILocation(line: 4, column: 10, scope: !29)
+!34 = !DILocation(line: 4, column: 19, scope: !29)
+!35 = !DILocation(line: 4, column: 30, scope: !29)
+!36 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
>From ed4c4a6abbebdbf5496cc74cc4aad688df534a9f Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 07:31:53 -0800
Subject: [PATCH 2/9] Apply clang-format
---
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
llvm/include/llvm/IR/DIBuilder.h | 4 ++--
llvm/lib/IR/DIBuilder.cpp | 5 +++--
llvm/lib/IR/Verifier.cpp | 4 ++--
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index d464a629443a4..ce2d34dcd4ce3 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3672,7 +3672,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const CodeGenModule &CGM) {
T = cast<MacroQualifiedType>(T)->getUnderlyingType();
break;
case Type::SubstTemplateTypeParm:
- if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
return C.getQualifiedType(T.getTypePtr(), Quals);
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 342b6d94c71f7..bb9b9490fdcdd 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -550,11 +550,11 @@ namespace llvm {
StringRef Name,
DIType *Ty,
bool IsDefault);
- /// \param Scope Scope in which this type is defined.
+ /// \param Scope Scope in which this type is defined.
/// \param Name Type parameter name.
/// \param Ty Parameter type.
DIDerivedType *createTemplateTypeParameterAsType(DIScope *Scope,
- StringRef Name,
+ StringRef Name,
DIType *Ty);
/// Create debugging information for template
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 8dc5677459bac..fc50077ba8736 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -462,8 +462,9 @@ DIDerivedType *DIBuilder::createTemplateTypeParameterAsType(DIScope *Context,
StringRef Name,
DIType *Ty) {
return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_type_parameter,
- Name, nullptr, 0, Context, Ty, 0, 0, 0, std::nullopt,
- std::nullopt, DINode::FlagZero, nullptr);
+ Name, nullptr, 0, Context, Ty, 0, 0, 0,
+ std::nullopt, std::nullopt, DINode::FlagZero,
+ nullptr);
}
DITemplateTypeParameter *
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c7435a629e23a..669c3370d9fc4 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1241,7 +1241,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type ||
- N.getTag() == dwarf::DW_TAG_template_type_parameter ||
+ N.getTag() == dwarf::DW_TAG_template_type_parameter ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
@@ -1289,7 +1289,7 @@ void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
CheckDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
- CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
+ CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
((isa<DIDerivedType>(Op)) &&
(dyn_cast<DIDerivedType>(Op)->getTag() ==
dwarf::DW_TAG_template_type_parameter)),
>From 022a8eb85929e7b5572483ee2d52ce60331417a6 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 18 Feb 2025 13:53:02 -0800
Subject: [PATCH 3/9] Update test to refelect review comment
---
.../DebugInfo/X86/template-as-type-param.ll | 143 +++++++++---------
1 file changed, 69 insertions(+), 74 deletions(-)
diff --git a/llvm/test/DebugInfo/X86/template-as-type-param.ll b/llvm/test/DebugInfo/X86/template-as-type-param.ll
index b237a6630ee7b..25eaeb92fec3e 100644
--- a/llvm/test/DebugInfo/X86/template-as-type-param.ll
+++ b/llvm/test/DebugInfo/X86/template-as-type-param.ll
@@ -1,5 +1,5 @@
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o %t -filetype=obj
-; RUN:llvm-dwarfdump %t | FileCheck %s
+; RUN: llvm-dwarfdump %t | FileCheck %s
;Source code for the IR below:
;template <typename T>
;struct A
@@ -16,30 +16,28 @@
; return 0;
;}
-;CHECK: DW_TAG_structure_type
-;CHECK: DW_AT_name ("A<int>")
-;CHECK-NEXT: DW_AT_byte_size (0x08)
-;CHECK-NEXT: DW_AT_decl_file ("/path/to{{/|\\}}test.cpp")
-;CHECK-NEXT: DW_AT_decl_line (2)
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_name ("A<int>")
+; CHECK-NEXT: DW_AT_byte_size (0x08)
+; CHECK-NEXT: DW_AT_decl_file ("test.cpp")
+; CHECK-NEXT: DW_AT_decl_line (2)
-;CHECK-NOT: NULL
+; CHECK-NOT: NULL
-;CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
-;CHECK-NEXT: DW_AT_type {{.*}} "int"
-;CHECK-NEXT: DW_AT_name ("T")
+; CHECK:[[TEMPLATE:0x[0-9a-f]*]]: DW_TAG_template_type_parameter
+; CHECK-NEXT: DW_AT_type {{.*}} "int"
+; CHECK-NEXT: DW_AT_name ("T")
-;CHECK: DW_TAG_member
-;CHECK-NEXT: DW_AT_name ("val_")
-;CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name ("val_")
+; CHECK-NEXT: DW_AT_type ([[TEMPLATE]] "T")
-;CHECK: DW_TAG_member
-;CHECK-NEXT: DW_AT_name ("val2_")
-;CHECK-NEXT: DW_AT_type {{.*}} "int"
-
-
-; ModuleID = '<stdin>'
+; CHECK: DW_TAG_member
+; CHECK-NEXT: DW_AT_name ("val2_")
+; CHECK-NEXT: DW_AT_type {{.*}} "int"
+; ModuleID = 'test.cpp'
source_filename = "test.cpp"
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%struct.A = type { i32, i32 }
@@ -47,78 +45,75 @@ target triple = "x86_64-unknown-linux-gnu"
$_ZN1AIiEC2Ev = comdat any
; Function Attrs: mustprogress noinline norecurse optnone uwtable
-define dso_local noundef i32 @main() #0 !dbg !20 {
+define dso_local noundef i32 @main() #0 !dbg !22 {
entry:
%retval = alloca i32, align 4
%a = alloca %struct.A, align 4
- store i32 0, i32* %retval, align 4
- call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !24, metadata !DIExpression()), !dbg !25
- call void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %a), !dbg !25
- %val2_ = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 1, !dbg !26
- store i32 3, i32* %val2_, align 4, !dbg !27
- ret i32 0, !dbg !28
+ store i32 0, ptr %retval, align 4
+ #dbg_declare(ptr %a, !26, !DIExpression(), !27)
+ call void @_ZN1AIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %a), !dbg !27
+ %val2_ = getelementptr inbounds nuw %struct.A, ptr %a, i32 0, i32 1, !dbg !28
+ store i32 3, ptr %val2_, align 4, !dbg !29
+ ret i32 0, !dbg !30
}
-; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-; Function Attrs: noinline nounwind optnone uwtable
-define linkonce_odr dso_local void @_ZN1AIiEC2Ev(%struct.A* noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 !dbg !29 {
-
+; Function Attrs: mustprogress noinline nounwind optnone uwtable
+define linkonce_odr dso_local void @_ZN1AIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 comdat align 2 !dbg !31 {
entry:
- %this.addr = alloca %struct.A*, align 8
- store %struct.A* %this, %struct.A** %this.addr, align 8
- call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !30, metadata !DIExpression()), !dbg !32
- %this1 = load %struct.A*, %struct.A** %this.addr, align 8
- %val_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 0, !dbg !33
- store i32 0, i32* %val_, align 4, !dbg !33
- %val2_ = getelementptr inbounds %struct.A, %struct.A* %this1, i32 0, i32 1, !dbg !34
- store i32 0, i32* %val2_, align 4, !dbg !34
- ret void, !dbg !35
+ %this.addr = alloca ptr, align 8
+ store ptr %this, ptr %this.addr, align 8
+ #dbg_declare(ptr %this.addr, !32, !DIExpression(), !34)
+ %this1 = load ptr, ptr %this.addr, align 8
+ %val_ = getelementptr inbounds nuw %struct.A, ptr %this1, i32 0, i32 0, !dbg !35
+ store i32 0, ptr %val_, align 4, !dbg !35
+ %val2_ = getelementptr inbounds nuw %struct.A, ptr %this1, i32 0, i32 1, !dbg !36
+ store i32 0, ptr %val2_, align 4, !dbg !36
+ ret void, !dbg !37
}
-attributes #0 = { mustprogress noinline norecurse 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 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
-attributes #2 = { 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 #0 = { mustprogress noinline norecurse 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"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { 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"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!14, !15, !16, !17, !18}
-!llvm.ident = !{!19}
+!llvm.module.flags = !{!14, !15, !16, !17, !18, !19, !20}
+!llvm.ident = !{!21}
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "", isOptimized: false, flags: " -S -g -O0 -emit-llvm reproducer.cxx -o reproducer.ll", runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
-!1 = !DIFile(filename: "test.cpp", directory: "/path/to")
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "", checksumkind: CSK_MD5, checksum: "451371997e00e9e85d610a4e9d44a9b5")
!2 = !{!3}
!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A<int>", file: !1, line: 2, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !4, templateParams: !12, identifier: "_ZTS1AIiE")
!4 = !{!5, !7, !8}
-!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 5, baseType: !36, size: 32,offset: 32)
+!5 = !DIDerivedType(tag: DW_TAG_member, name: "val_", scope: !3, file: !1, line: 4, baseType: !38, size: 32)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 6, baseType: !6, size: 32, offset: 32)
-!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: 0)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "val2_", scope: !3, file: !1, line: 5, baseType: !6, size: 32, offset: 32)
+!8 = !DISubprogram(name: "A", scope: !3, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: 0)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
-!12 = !{!36}
+!12 = !{!38}
!13 = !DITemplateTypeParameter(name: "T", type: !6)
-!14 = !{i32 7, !"Dwarf Version", i32 4}
+!14 = !{i32 7, !"Dwarf Version", i32 5}
!15 = !{i32 2, !"Debug Info Version", i32 3}
!16 = !{i32 1, !"wchar_size", i32 4}
-!17 = !{i32 7, !"uwtable", i32 2}
-!18 = !{i32 7, !"frame-pointer", i32 2}
-!19 = !{!""}
-!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 10, type: !21, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !23)
-!21 = !DISubroutineType(types: !22)
-!22 = !{!6}
-!23 = !{}
-!24 = !DILocalVariable(name: "a", scope: !20, file: !1, line: 12, type: !3)
-!25 = !DILocation(line: 12, column: 10, scope: !20)
-!26 = !DILocation(line: 13, column: 5, scope: !20)
-!27 = !DILocation(line: 13, column: 11, scope: !20)
-!28 = !DILocation(line: 15, column: 3, scope: !20)
-!29 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !23)
-!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
-!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
-!32 = !DILocation(line: 0, scope: !29)
-!33 = !DILocation(line: 4, column: 10, scope: !29)
-!34 = !DILocation(line: 4, column: 19, scope: !29)
-!35 = !DILocation(line: 4, column: 30, scope: !29)
-!36 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
+!17 = !{i32 8, !"PIC Level", i32 2}
+!18 = !{i32 7, !"PIE Level", i32 2}
+!19 = !{i32 7, !"uwtable", i32 2}
+!20 = !{i32 7, !"frame-pointer", i32 2}
+!21 = !{!"clang"}
+!22 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !23, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !25)
+!23 = !DISubroutineType(types: !24)
+!24 = !{!6}
+!25 = !{}
+!26 = !DILocalVariable(name: "a", scope: !22, file: !1, line: 8, type: !3)
+!27 = !DILocation(line: 8, column: 8, scope: !22)
+!28 = !DILocation(line: 9, column: 3, scope: !22)
+!29 = !DILocation(line: 9, column: 9, scope: !22)
+!30 = !DILocation(line: 10, column: 1, scope: !22)
+!31 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIiEC2Ev", scope: !3, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !8, retainedNodes: !25)
+!32 = !DILocalVariable(name: "this", arg: 1, scope: !31, type: !33, flags: DIFlagArtificial | DIFlagObjectPointer)
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64)
+!34 = !DILocation(line: 0, scope: !31)
+!35 = !DILocation(line: 3, column: 8, scope: !31)
+!36 = !DILocation(line: 3, column: 17, scope: !31)
+!37 = !DILocation(line: 3, column: 28, scope: !31)
+!38 = !DIDerivedType(tag: DW_TAG_template_type_parameter,name:"T",scope:!3, baseType: !6)
>From 81da81b71efd25f74f0eb449fbddc0746e2e12d6 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Wed, 26 Feb 2025 12:50:40 -0800
Subject: [PATCH 4/9] Add DIDerived type to template params
---
clang/lib/CodeGen/CGDebugInfo.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index ce2d34dcd4ce3..88936c4e8cc0e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2296,10 +2296,16 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
switch (TA.getKind()) {
case TemplateArgument::Type: {
- llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
+ {
+ llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
+ llvm::DIType *TemplateType = DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType);
+ TemplateParams.push_back(TemplateType);
+ }
+ else {llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
TheCU, Name, TTy, defaultParameter));
-
+ }
} break;
case TemplateArgument::Integral: {
llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);
>From d697eaafffb2d34ad01e60b2393e1d1eff2284aa Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Thu, 27 Feb 2025 08:06:39 -0800
Subject: [PATCH 5/9] Apply clang-format
---
clang/lib/CodeGen/CGDebugInfo.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 88936c4e8cc0e..8c6caee9bf705 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2296,15 +2296,15 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
switch (TA.getKind()) {
case TemplateArgument::Type: {
- if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
- {
- llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
- llvm::DIType *TemplateType = DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType);
- TemplateParams.push_back(TemplateType);
- }
- else {llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
- TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
- TheCU, Name, TTy, defaultParameter));
+ if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
+ llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
+ llvm::DIType *TemplateType =
+ DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType);
+ TemplateParams.push_back(TemplateType);
+ } else {
+ llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
+ TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
+ TheCU, Name, TTy, defaultParameter));
}
} break;
case TemplateArgument::Integral: {
>From db9fe2443c94d9dca034f6c8b980c06cc2e21b81 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 4 Mar 2025 11:24:48 -0800
Subject: [PATCH 6/9] Fix the scope of template types
---
clang/lib/CodeGen/CGDebugInfo.cpp | 18 +++++++++++-------
clang/lib/CodeGen/CGDebugInfo.h | 4 ++--
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8c6caee9bf705..1e815526f2b13 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1006,8 +1006,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *U) {
llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
+ auto *Tty = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl());
+ llvm::DIType *Scope = CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(),0),U);
return DBuilder.createTemplateTypeParameterAsType(
- U, Ty->getReplacedParameter()->getName(), debugType);
+ Scope, Ty->getReplacedParameter()->getName(), debugType);
}
llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
@@ -1248,7 +1250,7 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
- CollectCXXTemplateParams(TSpecial, DefUnit));
+ CollectCXXTemplateParams(TSpecial, DefUnit,RetTy));
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -2282,12 +2284,13 @@ void CGDebugInfo::CollectCXXBasesAux(
llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
- llvm::DIFile *Unit) {
+ llvm::DIFile *Unit, llvm::DICompositeType *RealDecl) {
if (!OArgs)
return llvm::DINodeArray();
TemplateArgs &Args = *OArgs;
SmallVector<llvm::Metadata *, 16> TemplateParams;
for (unsigned i = 0, e = Args.Args.size(); i != e; ++i) {
+
const TemplateArgument &TA = Args.Args[i];
StringRef Name;
const bool defaultParameter = TA.getIsDefaulted();
@@ -2298,8 +2301,9 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
case TemplateArgument::Type: {
if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
+ llvm::DIScope *Scope = RealDecl ? RealDecl : Unit;
llvm::DIType *TemplateType =
- DBuilder.createTemplateTypeParameterAsType(Unit, Name, debugType);
+ DBuilder.createTemplateTypeParameterAsType(Scope, Name, debugType);
TemplateParams.push_back(TemplateType);
} else {
llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
@@ -2471,8 +2475,8 @@ llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
}
llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD,
- llvm::DIFile *Unit) {
- return CollectTemplateParams(GetTemplateArgs(RD), Unit);
+ llvm::DIFile *Unit, llvm::DICompositeType *RealDecl) {
+ return CollectTemplateParams(GetTemplateArgs(RD), Unit, RealDecl);
}
llvm::DINodeArray CGDebugInfo::CollectBTFDeclTagAnnotations(const Decl *D) {
@@ -4010,7 +4014,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(),
- CollectCXXTemplateParams(TSpecial, DefUnit));
+ CollectCXXTemplateParams(TSpecial, DefUnit,RealDecl));
return RealDecl;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 5e28fd5bf9039..7fd09dc63c242 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -306,7 +306,7 @@ class CGDebugInfo {
};
/// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(std::optional<TemplateArgs> Args,
- llvm::DIFile *Unit);
+ llvm::DIFile *Unit,llvm::DICompositeType* RealDecl = nullptr);
/// A helper function to collect debug info for function template
/// parameters.
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
@@ -324,7 +324,7 @@ class CGDebugInfo {
/// A helper function to collect debug info for template
/// parameters.
llvm::DINodeArray CollectCXXTemplateParams(const RecordDecl *TS,
- llvm::DIFile *F);
+ llvm::DIFile *F, llvm::DICompositeType* RealDecl = nullptr);
/// A helper function to collect debug info for btf_decl_tag annotations.
llvm::DINodeArray CollectBTFDeclTagAnnotations(const Decl *D);
>From 270fe3076a362b1e4746c86dee1a4f5b887d0f93 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 4 Mar 2025 11:26:02 -0800
Subject: [PATCH 7/9] Apply clang-format
---
clang/lib/CodeGen/CGDebugInfo.cpp | 26 ++++++++++++++++----------
clang/lib/CodeGen/CGDebugInfo.h | 10 ++++++----
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 1e815526f2b13..20a4a3cf23d1e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1006,8 +1006,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *U) {
llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
- auto *Tty = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl());
- llvm::DIType *Scope = CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(),0),U);
+ auto *Tty =
+ dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl());
+ llvm::DIType *Scope =
+ CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(), 0), U);
return DBuilder.createTemplateTypeParameterAsType(
Scope, Ty->getReplacedParameter()->getName(), debugType);
}
@@ -1249,8 +1251,9 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
Identifier);
if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
- CollectCXXTemplateParams(TSpecial, DefUnit,RetTy));
+ DBuilder.replaceArrays(
+ RetTy, llvm::DINodeArray(),
+ CollectCXXTemplateParams(TSpecial, DefUnit, RetTy));
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
@@ -2284,7 +2287,8 @@ void CGDebugInfo::CollectCXXBasesAux(
llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
- llvm::DIFile *Unit, llvm::DICompositeType *RealDecl) {
+ llvm::DIFile *Unit,
+ llvm::DICompositeType *RealDecl) {
if (!OArgs)
return llvm::DINodeArray();
TemplateArgs &Args = *OArgs;
@@ -2301,7 +2305,7 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
case TemplateArgument::Type: {
if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
- llvm::DIScope *Scope = RealDecl ? RealDecl : Unit;
+ llvm::DIScope *Scope = RealDecl ? RealDecl : Unit;
llvm::DIType *TemplateType =
DBuilder.createTemplateTypeParameterAsType(Scope, Name, debugType);
TemplateParams.push_back(TemplateType);
@@ -2474,8 +2478,9 @@ llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
return CollectTemplateParams(GetTemplateArgs(VL), Unit);
}
-llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD,
- llvm::DIFile *Unit, llvm::DICompositeType *RealDecl) {
+llvm::DINodeArray
+CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD, llvm::DIFile *Unit,
+ llvm::DICompositeType *RealDecl) {
return CollectTemplateParams(GetTemplateArgs(RD), Unit, RealDecl);
}
@@ -4013,8 +4018,9 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(),
- CollectCXXTemplateParams(TSpecial, DefUnit,RealDecl));
+ DBuilder.replaceArrays(
+ RealDecl, llvm::DINodeArray(),
+ CollectCXXTemplateParams(TSpecial, DefUnit, RealDecl));
return RealDecl;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 7fd09dc63c242..daf256852b079 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -305,8 +305,9 @@ class CGDebugInfo {
llvm::ArrayRef<TemplateArgument> Args;
};
/// A helper function to collect template parameters.
- llvm::DINodeArray CollectTemplateParams(std::optional<TemplateArgs> Args,
- llvm::DIFile *Unit,llvm::DICompositeType* RealDecl = nullptr);
+ llvm::DINodeArray
+ CollectTemplateParams(std::optional<TemplateArgs> Args, llvm::DIFile *Unit,
+ llvm::DICompositeType *RealDecl = nullptr);
/// A helper function to collect debug info for function template
/// parameters.
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
@@ -323,8 +324,9 @@ class CGDebugInfo {
/// A helper function to collect debug info for template
/// parameters.
- llvm::DINodeArray CollectCXXTemplateParams(const RecordDecl *TS,
- llvm::DIFile *F, llvm::DICompositeType* RealDecl = nullptr);
+ llvm::DINodeArray
+ CollectCXXTemplateParams(const RecordDecl *TS, llvm::DIFile *F,
+ llvm::DICompositeType *RealDecl = nullptr);
/// A helper function to collect debug info for btf_decl_tag annotations.
llvm::DINodeArray CollectBTFDeclTagAnnotations(const Decl *D);
>From 5a2b35f2035134b2b6a511dd6761955cfe435550 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Thu, 6 Mar 2025 07:32:40 -0800
Subject: [PATCH 8/9] Fix nullptr crash
---
clang/lib/CodeGen/CGDebugInfo.cpp | 9 ++++-----
clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp | 5 +++--
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 20a4a3cf23d1e..4edd94c1c0f1c 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1006,10 +1006,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *U) {
llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
- auto *Tty =
- dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl());
- llvm::DIType *Scope =
- CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(), 0), U);
+ llvm::DIScope *Scope = static_cast<llvm::DIScope*>(U);
+ if(auto *Tty = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl()))
+ Scope = CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(), 0), U);
return DBuilder.createTemplateTypeParameterAsType(
Scope, Ty->getReplacedParameter()->getName(), debugType);
}
@@ -2305,7 +2304,7 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
case TemplateArgument::Type: {
if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
- llvm::DIScope *Scope = RealDecl ? RealDecl : Unit;
+ llvm::DIScope *Scope = RealDecl!=nullptr ? static_cast<llvm::DIScope*>(RealDecl) : static_cast<llvm::DIScope*>(Unit);
llvm::DIType *TemplateType =
DBuilder.createTemplateTypeParameterAsType(Scope, Name, debugType);
TemplateParams.push_back(TemplateType);
diff --git a/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
index 3422ce8f1e2bd..f7d624af1a557 100644
--- a/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
+++ b/clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
@@ -36,7 +36,8 @@ int main () {
// CHECK: [[TPARAM]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val2_",{{.*}}baseType: [[INT]]
-// CHECK: !DILocalVariable(name: "A",{{.*}}type: [[TPARAM]])
+// CHECK: !DILocalVariable(name: "A",{{.*}}type: [[TPARAM3:![0-9]+]])
+// CHECK: [[TPARAM3]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])
// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<double>"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM2:![0-9]+]]
@@ -49,4 +50,4 @@ int main () {
// CHECK: [[TPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[TPARAM]]
// CHECK: distinct !DISubprogram(name: "bar<int>"
-// CHECK: !DILocalVariable(name: "tp",{{.*}}type: [[TPARAM]])
+// CHECK: !DILocalVariable(name: "tp",{{.*}}type: [[TPARAM3]])
>From 48e6b656a07d1d825990e8b28b572a368e0a3ecb Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Thu, 6 Mar 2025 07:34:35 -0800
Subject: [PATCH 9/9] Apply clang-format
---
clang/lib/CodeGen/CGDebugInfo.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 4edd94c1c0f1c..28b52894f1244 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1006,8 +1006,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *U) {
llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
- llvm::DIScope *Scope = static_cast<llvm::DIScope*>(U);
- if(auto *Tty = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl()))
+ llvm::DIScope *Scope = static_cast<llvm::DIScope *>(U);
+ if (auto *Tty =
+ dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl()))
Scope = CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(), 0), U);
return DBuilder.createTemplateTypeParameterAsType(
Scope, Ty->getReplacedParameter()->getName(), debugType);
@@ -2304,7 +2305,9 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
case TemplateArgument::Type: {
if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
- llvm::DIScope *Scope = RealDecl!=nullptr ? static_cast<llvm::DIScope*>(RealDecl) : static_cast<llvm::DIScope*>(Unit);
+ llvm::DIScope *Scope = RealDecl != nullptr
+ ? static_cast<llvm::DIScope *>(RealDecl)
+ : static_cast<llvm::DIScope *>(Unit);
llvm::DIType *TemplateType =
DBuilder.createTemplateTypeParameterAsType(Scope, Name, debugType);
TemplateParams.push_back(TemplateType);
More information about the cfe-commits
mailing list