[Lldb-commits] [lldb] [lldb][NativePDB] Fix width and signedness of enum constants (PR #210338)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 17 07:06:47 PDT 2026
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/210338
>From e1f62acc74b75014580361e58a7709a4689d7985 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 17 Jul 2026 15:37:48 +0200
Subject: [PATCH 1/3] [lldb][NativePDB] Fix width and signedness of enum
constants
---
.../NativePDB/UdtRecordCompleter.cpp | 18 +++-
lldb/test/API/lang/cpp/enum-limits/Makefile | 3 +
.../lang/cpp/enum-limits/TestCPPEnumLimits.py | 91 +++++++++++++++++++
lldb/test/API/lang/cpp/enum-limits/main.cpp | 48 ++++++++++
4 files changed, 159 insertions(+), 1 deletion(-)
create mode 100644 lldb/test/API/lang/cpp/enum-limits/Makefile
create mode 100644 lldb/test/API/lang/cpp/enum-limits/TestCPPEnumLimits.py
create mode 100644 lldb/test/API/lang/cpp/enum-limits/main.cpp
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 9840b976d2713..871b053151c61 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -331,8 +331,24 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
Declaration decl;
llvm::StringRef name = DropNameScope(enumerator.getName());
+ clang::EnumDecl *enum_decl = TypeSystemClang::GetAsEnumDecl(m_derived_ct);
+ if (!enum_decl)
+ return Error::success();
+
+ llvm::APSInt val = enumerator.Value;
+ clang::QualType int_ty = enum_decl->getIntegerType();
+ uint64_t n_bits = m_ast_builder.clang().getASTContext().getTypeSize(int_ty);
+ if (n_bits == 0)
+ return Error::success();
+
+ // MSVC encodes 64 Bit unsigned enum values as signed integers. For example,
+ // ULONGLONG_MAX will be encoded as -1. LLVM encodes all values as unsigned.
+ // Fix this by explicitly setting the bit width and signedness.
+ val = val.extOrTrunc(n_bits);
+ val.setIsSigned(int_ty->isSignedIntegerType());
+
m_ast_builder.clang().AddEnumerationValueToEnumerationType(
- m_derived_ct, decl, name.str().c_str(), enumerator.Value);
+ m_derived_ct, decl, name.str().c_str(), val);
return Error::success();
}
diff --git a/lldb/test/API/lang/cpp/enum-limits/Makefile b/lldb/test/API/lang/cpp/enum-limits/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum-limits/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/enum-limits/TestCPPEnumLimits.py b/lldb/test/API/lang/cpp/enum-limits/TestCPPEnumLimits.py
new file mode 100644
index 0000000000000..4e0c0a088c909
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum-limits/TestCPPEnumLimits.py
@@ -0,0 +1,91 @@
+"""Check that enumerator values are correct when they're near the limits of the underlying type."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class CPPEnumLimitsTestCase(TestBase):
+ SHARED_BUILD_TESTCASE = False
+ TEST_WITH_PDB_DEBUG_INFO = True
+
+ def check_signed(self, ty: lldb.SBType, expected):
+ self.assertEqual(
+ {i.GetName(): i.GetValueAsSigned() for i in ty.GetEnumMembers()}, expected
+ )
+
+ def check_unsigned(self, ty: lldb.SBType, expected):
+ self.assertEqual(
+ {i.GetName(): i.GetValueAsUnsigned() for i in ty.GetEnumMembers()}, expected
+ )
+
+ def check_all(self, target: lldb.SBTarget):
+ self.check_unsigned(target.FindFirstType("U8Enum"), {"Min": 0, "Max": 255})
+ self.check_signed(target.FindFirstType("I8Enum"), {"Min": -128, "Max": 127})
+ self.check_unsigned(target.FindFirstType("U16Enum"), {"Min": 0, "Max": 65535})
+ self.check_signed(
+ target.FindFirstType("I16Enum"), {"Min": -32768, "Max": 32767}
+ )
+ self.check_unsigned(
+ target.FindFirstType("U32Enum"),
+ {"Min": 0, "MaxMinusOne": 4294967294, "Max": 4294967295},
+ )
+ self.check_signed(
+ target.FindFirstType("I32Enum"), {"Min": -2147483648, "Max": 2147483647}
+ )
+ self.check_unsigned(
+ target.FindFirstType("U64Enum"),
+ {
+ "Min": 0,
+ "MaxMinusOne": 18446744073709551614,
+ "Max": 18446744073709551615,
+ },
+ )
+ self.check_signed(
+ target.FindFirstType("I64Enum"),
+ {
+ "Min": -9223372036854775808,
+ "MinPlusOne": -9223372036854775807,
+ "MaxMinusOne": 9223372036854775806,
+ "Max": 9223372036854775807,
+ },
+ )
+
+ def test(self):
+ self.build()
+ self.check_all(self.dbg.CreateTarget(self.getBuildArtifact("a.out")))
+
+ @skipUnlessPlatform(["windows"])
+ @skipUnlessMSVC
+ @no_debug_info_test # We only test MSVC
+ def test_msvc(self):
+ """Test that the limits work on MSVC."""
+
+ src = os.path.join(self.getSourceDir(), "main.cpp")
+ exe = os.path.join(self.getBuildDir(), "a.exe")
+
+ # FIXME: Allow MSVC to be used with the Makefile.
+ result = subprocess.run(
+ [
+ "cl.exe",
+ "/nologo",
+ "/Od",
+ "/Zi",
+ "/Fe" + exe,
+ src,
+ "/link",
+ "/nodefaultlib",
+ "/entry:main",
+ ],
+ cwd=self.getBuildDir(),
+ capture_output=True,
+ text=True,
+ )
+ self.assertEqual(
+ result.returncode,
+ 0,
+ "Compilation failed:\n" + result.stdout + result.stderr,
+ )
+
+ self.check_all(self.dbg.CreateTarget(exe))
diff --git a/lldb/test/API/lang/cpp/enum-limits/main.cpp b/lldb/test/API/lang/cpp/enum-limits/main.cpp
new file mode 100644
index 0000000000000..3aeef3fd03e01
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum-limits/main.cpp
@@ -0,0 +1,48 @@
+enum class U8Enum : unsigned char {
+ Min = 0,
+ Max = 255,
+};
+enum class I8Enum : char {
+ Min = -128,
+ Max = 127,
+};
+enum class U16Enum : unsigned short {
+ Min = 0,
+ Max = 65535,
+};
+enum class I16Enum : short {
+ Min = -32768,
+ Max = 32767,
+};
+enum class U32Enum : unsigned {
+ Min = 0,
+ MaxMinusOne = 4294967294,
+ Max = 4294967295,
+};
+enum class I32Enum : int {
+ Min = -2147483648,
+ Max = 2147483647,
+};
+enum class U64Enum : unsigned long long {
+ Min = 0,
+ MaxMinusOne = 18446744073709551614ULL,
+ Max = 18446744073709551615ULL,
+};
+enum class I64Enum : long long {
+ Min = -9223372036854775807LL - 1,
+ MinPlusOne = -9223372036854775807LL,
+ MaxMinusOne = 9223372036854775806LL,
+ Max = 9223372036854775807LL,
+};
+
+int main(){
+ auto u8 = U8Enum::Max;
+ auto i8 = I8Enum::Max;
+ auto u16 = U16Enum::Max;
+ auto i16 = I16Enum::Max;
+ auto u32 = U32Enum::Max;
+ auto i32 = I32Enum::Max;
+ auto u64 = U64Enum::Max;
+ auto i64 = I64Enum::Max;
+ return 0;
+}
>From 5ed10b2826735de4c8e8e3d4aa297c4d5920441d Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 17 Jul 2026 15:52:12 +0200
Subject: [PATCH 2/3] fix: formatting
---
lldb/test/API/lang/cpp/enum-limits/main.cpp | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/lldb/test/API/lang/cpp/enum-limits/main.cpp b/lldb/test/API/lang/cpp/enum-limits/main.cpp
index 3aeef3fd03e01..b8855b5920e21 100644
--- a/lldb/test/API/lang/cpp/enum-limits/main.cpp
+++ b/lldb/test/API/lang/cpp/enum-limits/main.cpp
@@ -35,14 +35,14 @@ enum class I64Enum : long long {
Max = 9223372036854775807LL,
};
-int main(){
- auto u8 = U8Enum::Max;
- auto i8 = I8Enum::Max;
- auto u16 = U16Enum::Max;
- auto i16 = I16Enum::Max;
- auto u32 = U32Enum::Max;
- auto i32 = I32Enum::Max;
- auto u64 = U64Enum::Max;
- auto i64 = I64Enum::Max;
- return 0;
+int main() {
+ auto u8 = U8Enum::Max;
+ auto i8 = I8Enum::Max;
+ auto u16 = U16Enum::Max;
+ auto i16 = I16Enum::Max;
+ auto u32 = U32Enum::Max;
+ auto i32 = I32Enum::Max;
+ auto u64 = U64Enum::Max;
+ auto i64 = I64Enum::Max;
+ return 0;
}
>From 9f1fcf5d28a4765f9c3037ecbba4b024ee8f09f8 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 17 Jul 2026 16:06:31 +0200
Subject: [PATCH 3/3] fix: use signed char
---
lldb/test/API/lang/cpp/enum-limits/main.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/lang/cpp/enum-limits/main.cpp b/lldb/test/API/lang/cpp/enum-limits/main.cpp
index b8855b5920e21..ea7036f7f7c0e 100644
--- a/lldb/test/API/lang/cpp/enum-limits/main.cpp
+++ b/lldb/test/API/lang/cpp/enum-limits/main.cpp
@@ -2,7 +2,7 @@ enum class U8Enum : unsigned char {
Min = 0,
Max = 255,
};
-enum class I8Enum : char {
+enum class I8Enum : signed char {
Min = -128,
Max = 127,
};
More information about the lldb-commits
mailing list