[llvm] [Dwarf] Don't crash in dwarf::isC() on vendor-defined languages (PR #223739)

Matt Davis via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 04:51:12 PDT 2026


https://github.com/enferex updated https://github.com/llvm/llvm-project/pull/223739

>From 3cba5954f7d1e71db2fc50c27f4a5a32989dac1d Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Sat, 29 Aug 2026 12:47:07 +0000
Subject: [PATCH 1/4] Don't crash in dwarf::isC() on vendor-defined languages

isC() enumerates every known SourceLanguage and falls off the end of the
switch into llvm_unreachable("Unknown language kind."). DW_LANG_lo_user
and DW_LANG_hi_user are both explicit cases, but every vendor-defined
code strictly between them is not, so any of them aborts an
asserts-enabled build.

Assisted-by: LLM
---
 llvm/include/llvm/BinaryFormat/Dwarf.h        |  5 ++++
 .../DebugInfo/X86/vendor-source-language.ll   | 26 +++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 llvm/test/DebugInfo/X86/vendor-source-language.ll

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 502f42b9ddc7e..193e4ddbd71fb 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -825,6 +825,11 @@ inline bool isC(SourceLanguage S) {
   case DW_LANG_Gleam:
     return false;
   }
+  // The switch above covers the DW_LANG_{lo,hi}_user boundaries, but every
+  // vendor-defined code in between is a valid SourceLanguage that no case
+  // enumerates. None of them is C.
+  if (S > DW_LANG_lo_user && S < DW_LANG_hi_user)
+    return false;
   llvm_unreachable("Unknown language kind.");
 }
 
diff --git a/llvm/test/DebugInfo/X86/vendor-source-language.ll b/llvm/test/DebugInfo/X86/vendor-source-language.ll
new file mode 100644
index 0000000000000..bff9a363159d9
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/vendor-source-language.ll
@@ -0,0 +1,26 @@
+; DW_LANG_lo_user and DW_LANG_hi_user are enumerated by dwarf::isC(), but the
+; vendor-defined codes between them are not, and used to fall through to the
+; trailing llvm_unreachable. Emitting a prototyped subprogram in such a
+; language calls isC() and must not crash.
+
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t.o < %s
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s
+
+; CHECK: DW_TAG_compile_unit
+; CHECK:   DW_AT_language (0x8003)
+
+define void @f() !dbg !4 {
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+; 32771 == DW_LANG_lo_user (0x8000) + 3, a vendor-defined source language.
+!0 = distinct !DICompileUnit(language: 32771, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "a.c", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !{i32 2, !"Dwarf Version", i32 5}
+!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, unit: !0, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}

>From 5fcd354fef24822a9ad3cdbc70437358d3e108ab Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Fri, 18 Sep 2026 12:32:55 +0000
Subject: [PATCH 2/4] Refactor Dwarf::isC to be closer to isFortran/isCPlusPlus

---
 llvm/include/llvm/BinaryFormat/Dwarf.h | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 193e4ddbd71fb..d04bfce5dfc25 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -742,6 +742,7 @@ inline bool isFortran(SourceLanguage S) {
 }
 
 inline bool isC(SourceLanguage S) {
+  bool result = false;
   // Deliberately enumerate all the language options so we get a warning when
   // new language options are added (-Wswitch) that'll hopefully help keep this
   // switch up-to-date when new C++ versions are added.
@@ -753,7 +754,8 @@ inline bool isC(SourceLanguage S) {
   case DW_LANG_C99:
   case DW_LANG_C:
   case DW_LANG_ObjC:
-    return true;
+    result = true;
+    break;
   case DW_LANG_C_plus_plus:
   case DW_LANG_C_plus_plus_03:
   case DW_LANG_C_plus_plus_11:
@@ -823,14 +825,11 @@ inline bool isC(SourceLanguage S) {
   case DW_LANG_Erlang:
   case DW_LANG_Elixir:
   case DW_LANG_Gleam:
-    return false;
+    result = false;
+    break;
   }
-  // The switch above covers the DW_LANG_{lo,hi}_user boundaries, but every
-  // vendor-defined code in between is a valid SourceLanguage that no case
-  // enumerates. None of them is C.
-  if (S > DW_LANG_lo_user && S < DW_LANG_hi_user)
-    return false;
-  llvm_unreachable("Unknown language kind.");
+
+  return result;
 }
 
 inline TypeKind getArrayIndexTypeEncoding(SourceLanguage S) {

>From 78d523672b206bc6c9a07a04b15d3071801a8ef9 Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Fri, 18 Sep 2026 14:21:20 +0000
Subject: [PATCH 3/4] Return early in Dwarf::isC instead of capturing state.

---
 llvm/include/llvm/BinaryFormat/Dwarf.h | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index d04bfce5dfc25..fe2c73b28ad20 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -742,7 +742,6 @@ inline bool isFortran(SourceLanguage S) {
 }
 
 inline bool isC(SourceLanguage S) {
-  bool result = false;
   // Deliberately enumerate all the language options so we get a warning when
   // new language options are added (-Wswitch) that'll hopefully help keep this
   // switch up-to-date when new C++ versions are added.
@@ -754,8 +753,7 @@ inline bool isC(SourceLanguage S) {
   case DW_LANG_C99:
   case DW_LANG_C:
   case DW_LANG_ObjC:
-    result = true;
-    break;
+    return true;
   case DW_LANG_C_plus_plus:
   case DW_LANG_C_plus_plus_03:
   case DW_LANG_C_plus_plus_11:
@@ -825,11 +823,10 @@ inline bool isC(SourceLanguage S) {
   case DW_LANG_Erlang:
   case DW_LANG_Elixir:
   case DW_LANG_Gleam:
-    result = false;
-    break;
+    return false;
   }
 
-  return result;
+  return false;
 }
 
 inline TypeKind getArrayIndexTypeEncoding(SourceLanguage S) {

>From 706b812d96b55f8581e068fa6417016180b9ce3e Mon Sep 17 00:00:00 2001
From: Matt Davis <mattd at nvidia.com>
Date: Mon, 21 Sep 2026 11:49:54 +0000
Subject: [PATCH 4/4] Minor grammatical correction.

---
 llvm/test/DebugInfo/X86/vendor-source-language.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/DebugInfo/X86/vendor-source-language.ll b/llvm/test/DebugInfo/X86/vendor-source-language.ll
index bff9a363159d9..8671a7aabcbdd 100644
--- a/llvm/test/DebugInfo/X86/vendor-source-language.ll
+++ b/llvm/test/DebugInfo/X86/vendor-source-language.ll
@@ -1,5 +1,5 @@
 ; DW_LANG_lo_user and DW_LANG_hi_user are enumerated by dwarf::isC(), but the
-; vendor-defined codes between them are not, and used to fall through to the
+; vendor-defined codes between them are not, and used to fall through to a
 ; trailing llvm_unreachable. Emitting a prototyped subprogram in such a
 ; language calls isC() and must not crash.
 



More information about the llvm-commits mailing list