[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