[llvm] [DebugInfo][LLVM IR] Verifier checks for the extraData (PR #167971)

Laxman Sole via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 17 12:00:22 PST 2025


https://github.com/laxmansole updated https://github.com/llvm/llvm-project/pull/167971

>From dbd2f08dacf696b5ea1a9d21da28872883e3c2a9 Mon Sep 17 00:00:00 2001
From: Laxman Sole <lsole at nvidia.com>
Date: Thu, 13 Nov 2025 14:07:37 -0800
Subject: [PATCH 1/3] Verifier checks for the extraData

---
 llvm/lib/IR/Verifier.cpp | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index fa18c3cd0f404..b01ca73aa3623 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1320,6 +1320,23 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
   if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
     CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
             N.getRawExtraData());
+  } else if (N.getTag() == dwarf::DW_TAG_template_alias) {
+    CheckDI(isa<MDTuple>(N.getRawExtraData()), "invalid template parameters",
+            &N, N.getRawExtraData());
+  } else if (auto *ExtraData = N.getRawExtraData()) {
+    auto IsValidExtraData = [&]() {
+      if (isa<ConstantAsMetadata>(ExtraData) || isa<MDString>(ExtraData) ||
+          isa<DIObjCProperty>(ExtraData))
+        return true;
+      if (auto *Tuple = dyn_cast<MDTuple>(ExtraData))
+        return Tuple->getNumOperands() == 1 &&
+               isa<ConstantAsMetadata>(Tuple->getOperand(0));
+      return false;
+    };
+    CheckDI(IsValidExtraData(),
+            "extraData must be ConstantAsMetadata, MDString, DIObjCProperty, "
+            "or MDTuple with single ConstantAsMetadata operand",
+            &N, ExtraData);
   }
 
   if (N.getTag() == dwarf::DW_TAG_set_type) {

>From 43ce782044eccbe1a5d465f2767112d49794bd12 Mon Sep 17 00:00:00 2001
From: Laxman Sole <lsole at nvidia.com>
Date: Fri, 14 Nov 2025 19:06:55 -0800
Subject: [PATCH 2/3] Updating verifier checks for to handle null references
 and adding lit test

---
 llvm/lib/IR/Verifier.cpp                      | 17 +++--
 .../Verifier/diderivedtype-extradata-tuple.ll | 66 +++++++++++++++++++
 2 files changed, 78 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/Verifier/diderivedtype-extradata-tuple.ll

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b01ca73aa3623..c60f9c4808420 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1158,6 +1158,7 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) {
 static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); }
 static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); }
 static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); }
+static bool isMDTuple(const Metadata *MD) { return !MD || isa<MDTuple>(MD); }
 
 void Verifier::visitDILocation(const DILocation &N) {
   CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
@@ -1321,16 +1322,22 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
     CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
             N.getRawExtraData());
   } else if (N.getTag() == dwarf::DW_TAG_template_alias) {
-    CheckDI(isa<MDTuple>(N.getRawExtraData()), "invalid template parameters",
-            &N, N.getRawExtraData());
+    CheckDI(isMDTuple(N.getRawExtraData()), "invalid template parameters", &N,
+            N.getRawExtraData());
   } else if (auto *ExtraData = N.getRawExtraData()) {
     auto IsValidExtraData = [&]() {
       if (isa<ConstantAsMetadata>(ExtraData) || isa<MDString>(ExtraData) ||
           isa<DIObjCProperty>(ExtraData))
         return true;
-      if (auto *Tuple = dyn_cast<MDTuple>(ExtraData))
-        return Tuple->getNumOperands() == 1 &&
-               isa<ConstantAsMetadata>(Tuple->getOperand(0));
+      if (auto *Tuple = dyn_cast<MDTuple>(ExtraData)) {
+        if (N.getTag() != dwarf::DW_TAG_inheritance &&
+            N.getTag() != dwarf::DW_TAG_member &&
+            N.getTag() != dwarf::DW_TAG_variable)
+          return false;
+        if (Tuple->getNumOperands() != 1)
+          return false;
+        return isa_and_nonnull<ConstantAsMetadata>(Tuple->getOperand(0).get());
+      }
       return false;
     };
     CheckDI(IsValidExtraData(),
diff --git a/llvm/test/Verifier/diderivedtype-extradata-tuple.ll b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll
new file mode 100644
index 0000000000000..e3f7a46bf905b
--- /dev/null
+++ b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll
@@ -0,0 +1,66 @@
+; RUN: not opt -S < %s 2>&1 | FileCheck %s
+
+;; Test that extraData with MDTuple is only allowed for specific DWARF tags:
+;; DW_TAG_inheritance, DW_TAG_member, and DW_TAG_variable
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+
+!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+; Keep all metadata nodes alive so verifier can check them
+!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19}
+!2 = !{i32 0}
+
+; Valid: DW_TAG_inheritance with tuple extraData should be accepted
+!3 = !DIDerivedType(tag: DW_TAG_inheritance, baseType: !1, size: 32, extraData: !2)
+
+; Valid: DW_TAG_member with tuple extraData should be accepted
+!4 = !DIDerivedType(tag: DW_TAG_member, name: "field", baseType: !1, size: 32, extraData: !2)
+
+; Valid: DW_TAG_variable (static member) with tuple extraData should be accepted
+!5 = !DIDerivedType(tag: DW_TAG_variable, name: "var", baseType: !1, extraData: !2, flags: DIFlagStaticMember)
+
+; Invalid: DW_TAG_typedef with tuple extraData should be rejected
+; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
+; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_typedef
+!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy", baseType: !1, extraData: !2)
+
+; Invalid: Empty tuple should be rejected
+!7 = !{}
+; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
+; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !7)
+
+; Invalid: Tuple with multiple operands should be rejected
+!9 = !{i32 0, i32 1}
+; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
+; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !9)
+
+; Invalid: Tuple with non-ConstantAsMetadata operand should be rejected
+!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!12 = !{!11}
+; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
+; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !12)
+
+; Valid: ConstantAsMetadata as extraData should still work for any tag
+!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy2", baseType: !1, extraData: i32 42)
+
+; Valid: MDString as extraData should still work for any tag
+!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy3", baseType: !1, extraData: !"some string")
+
+; Valid: DW_TAG_template_alias with proper template parameters tuple
+; Template aliases are handled specially and accept any MDTuple for template parameters
+!16 = !DITemplateTypeParameter(name: "T", type: !1)
+!17 = !{!16}
+!18 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !17)
+
+; Invalid: DW_TAG_template_alias with non-tuple extraData should fail
+; CHECK: invalid template parameters
+; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_template_alias
+!19 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42)
+
+; CHECK: warning: ignoring invalid debug info
+

>From bff5946e237945fab1d9d2bad289f107363a8c70 Mon Sep 17 00:00:00 2001
From: Laxman Sole <lsole at nvidia.com>
Date: Mon, 17 Nov 2025 10:54:09 -0800
Subject: [PATCH 3/3] updating verifier checks only for specific tags

---
 llvm/lib/IR/Verifier.cpp                      | 11 +++---
 .../Verifier/diderivedtype-extradata-tuple.ll | 35 +++++++------------
 2 files changed, 18 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c60f9c4808420..92e7b7530b038 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1324,16 +1324,17 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
   } else if (N.getTag() == dwarf::DW_TAG_template_alias) {
     CheckDI(isMDTuple(N.getRawExtraData()), "invalid template parameters", &N,
             N.getRawExtraData());
-  } else if (auto *ExtraData = N.getRawExtraData()) {
+  } else if (N.getTag() == dwarf::DW_TAG_inheritance ||
+             N.getTag() == dwarf::DW_TAG_member ||
+             N.getTag() == dwarf::DW_TAG_variable) {
+    auto *ExtraData = N.getRawExtraData();
     auto IsValidExtraData = [&]() {
+      if (ExtraData == nullptr)
+        return true;
       if (isa<ConstantAsMetadata>(ExtraData) || isa<MDString>(ExtraData) ||
           isa<DIObjCProperty>(ExtraData))
         return true;
       if (auto *Tuple = dyn_cast<MDTuple>(ExtraData)) {
-        if (N.getTag() != dwarf::DW_TAG_inheritance &&
-            N.getTag() != dwarf::DW_TAG_member &&
-            N.getTag() != dwarf::DW_TAG_variable)
-          return false;
         if (Tuple->getNumOperands() != 1)
           return false;
         return isa_and_nonnull<ConstantAsMetadata>(Tuple->getOperand(0).get());
diff --git a/llvm/test/Verifier/diderivedtype-extradata-tuple.ll b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll
index e3f7a46bf905b..9258d1db76aff 100644
--- a/llvm/test/Verifier/diderivedtype-extradata-tuple.ll
+++ b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll
@@ -9,7 +9,7 @@
 !1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 
 ; Keep all metadata nodes alive so verifier can check them
-!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19}
+!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16}
 !2 = !{i32 0}
 
 ; Valid: DW_TAG_inheritance with tuple extraData should be accepted
@@ -21,46 +21,35 @@
 ; Valid: DW_TAG_variable (static member) with tuple extraData should be accepted
 !5 = !DIDerivedType(tag: DW_TAG_variable, name: "var", baseType: !1, extraData: !2, flags: DIFlagStaticMember)
 
-; Invalid: DW_TAG_typedef with tuple extraData should be rejected
-; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
-; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_typedef
-!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy", baseType: !1, extraData: !2)
-
 ; Invalid: Empty tuple should be rejected
-!7 = !{}
+!6 = !{}
 ; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
 ; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
-!8 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !7)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !6)
 
 ; Invalid: Tuple with multiple operands should be rejected
-!9 = !{i32 0, i32 1}
+!8 = !{i32 0, i32 1}
 ; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
 ; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
-!10 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !9)
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !8)
 
 ; Invalid: Tuple with non-ConstantAsMetadata operand should be rejected
-!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
-!12 = !{!11}
+!10 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!11 = !{!10}
 ; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
 ; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
-!13 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !12)
-
-; Valid: ConstantAsMetadata as extraData should still work for any tag
-!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy2", baseType: !1, extraData: i32 42)
-
-; Valid: MDString as extraData should still work for any tag
-!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy3", baseType: !1, extraData: !"some string")
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !11)
 
 ; Valid: DW_TAG_template_alias with proper template parameters tuple
 ; Template aliases are handled specially and accept any MDTuple for template parameters
-!16 = !DITemplateTypeParameter(name: "T", type: !1)
-!17 = !{!16}
-!18 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !17)
+!13 = !DITemplateTypeParameter(name: "T", type: !1)
+!14 = !{!13}
+!15 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !14)
 
 ; Invalid: DW_TAG_template_alias with non-tuple extraData should fail
 ; CHECK: invalid template parameters
 ; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_template_alias
-!19 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42)
+!16 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42)
 
 ; CHECK: warning: ignoring invalid debug info
 



More information about the llvm-commits mailing list