[clang] [llvm] Template as type (PR #127654)

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 18 13:53:30 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/3] 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/3] 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/3] 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)



More information about the llvm-commits mailing list