[Lldb-commits] [lldb] [lldb] Add enum lookup to DIL (PR #192065)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 14 07:12:53 PDT 2026
https://github.com/kuilpd created https://github.com/llvm/llvm-project/pull/192065
None
>From 951478c2183f3ee180574d9d11182825be8110ae Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 26 Mar 2026 21:42:43 +0500
Subject: [PATCH] [lldb] Add enum lookup to DIL
---
lldb/include/lldb/ValueObject/DILEval.h | 5 +++
lldb/include/lldb/ValueObject/DILParser.h | 2 ++
lldb/source/ValueObject/DILEval.cpp | 29 +++++++++++++++
lldb/source/ValueObject/DILParser.cpp | 6 ++--
.../var-dil/expr/EnumValueLookup/Makefile | 3 ++
.../EnumValueLookup/TestEnumValueLookup.py | 36 +++++++++++++++++++
.../var-dil/expr/EnumValueLookup/main.cpp | 19 ++++++++++
7 files changed, 97 insertions(+), 3 deletions(-)
create mode 100644 lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/Makefile
create mode 100644 lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/TestEnumValueLookup.py
create mode 100644 lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/main.cpp
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index c5f41b5a0bc76..aa524cb420339 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -36,6 +36,11 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
lldb::TargetSP target_sp,
lldb::DynamicValueType use_dynamic);
+/// Given the name of an identifier, attempt to find an enumeration value.
+/// If found, return a ValueObject with a const scalar value of the enum.
+lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
+ std::shared_ptr<StackFrame> frame_sp);
+
class Interpreter : Visitor {
public:
Interpreter(lldb::TargetSP target, llvm::StringRef expr,
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index 351eea6d0d268..deb39ada787a1 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -37,6 +37,8 @@ enum class ErrorCode : unsigned char {
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx);
+CompilerType ResolveTypeByName(const std::string &name,
+ std::shared_ptr<StackFrame> stack_frame);
// The following is modeled on class OptionParseError.
class DILDiagnosticError
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 7801b9225f19e..75385b95b7aae 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -380,6 +380,31 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
return nullptr;
}
+lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
+ std::shared_ptr<StackFrame> stack_frame) {
+ if (name_ref.contains("::")) {
+ llvm::StringRef enum_typename, enumerator_name;
+ // FIXME: Change this to a structured binding for lambda capturing
+ // once we have C++20.
+ std::tie(enum_typename, enumerator_name) = name_ref.rsplit("::");
+ auto enum_type = ResolveTypeByName(enum_typename.str(), stack_frame);
+ lldb::ValueObjectSP result;
+ enum_type.ForEachEnumerator([&](const CompilerType &integer_type,
+ ConstString name,
+ const llvm::APSInt &value) -> bool {
+ if (name == enumerator_name) {
+ Scalar scalar(value);
+ result = ValueObject::CreateValueObjectFromScalar(stack_frame, scalar,
+ enum_type, "result");
+ return false; // Stop iterating
+ }
+ return true;
+ });
+ return result;
+ }
+ return nullptr;
+}
+
Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
std::shared_ptr<StackFrame> frame_sp,
lldb::DynamicValueType use_dynamic, uint32_t options)
@@ -439,6 +464,10 @@ Interpreter::Visit(const IdentifierNode &node) {
if (!identifier)
identifier = LookupGlobalIdentifier(node.GetName(), m_exe_ctx_scope,
m_target, use_dynamic);
+
+ if (!identifier)
+ identifier = LookupEnumValue(node.GetName(), m_exe_ctx_scope);
+
if (!identifier) {
std::string errMsg =
llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index 51bdffd5087ca..11b4ecd827cb4 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -70,7 +70,7 @@ GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) {
}
CompilerType ResolveTypeByName(const std::string &name,
- ExecutionContextScope &ctx_scope) {
+ std::shared_ptr<StackFrame> stack_frame) {
// Internally types don't have global scope qualifier in their names and
// LLDB doesn't support queries with it too.
llvm::StringRef name_ref(name);
@@ -79,7 +79,7 @@ CompilerType ResolveTypeByName(const std::string &name,
name_ref = name_ref.drop_front(2);
std::vector<CompilerType> result_type_list;
- lldb::TargetSP target_sp = ctx_scope.CalculateTarget();
+ lldb::TargetSP target_sp = stack_frame->CalculateTarget();
if (!name_ref.empty() && target_sp) {
ModuleList &images = target_sp->GetImages();
TypeQuery query{ConstString(name_ref), TypeQueryOptions::e_exact_match |
@@ -469,7 +469,7 @@ std::optional<CompilerType> DILParser::ParseTypeId() {
if (type_name.empty())
return {};
- type = ResolveTypeByName(type_name, *m_ctx_scope);
+ type = ResolveTypeByName(type_name, m_ctx_scope);
if (!type.IsValid())
return {};
diff --git a/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/Makefile b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/TestEnumValueLookup.py b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/TestEnumValueLookup.py
new file mode 100644
index 0000000000000..e0a0ffd6be048
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/TestEnumValueLookup.py
@@ -0,0 +1,36 @@
+"""
+Test DIL enum value lookups.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestEnumValueLookup(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_literals(self):
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+ )
+
+ self.runCmd("settings set target.experimental.use-DIL true")
+
+ self.expect_var_path("enum_one", value="kOne", type="UnscopedEnum")
+ self.expect_var_path("UnscopedEnum::kOne", value="kOne", type="UnscopedEnum")
+ self.expect_var_path(
+ "UnscopedEnumInt8::kOne8", value="kOne8", type="UnscopedEnumInt8"
+ )
+ self.expect_var_path("ScopedEnum::kOneS", value="kOneS", type="ScopedEnum")
+ self.expect_var_path(
+ "ns::NSUnscopedEnum::kOneNS", value="kOneNS", type="ns::NSUnscopedEnum"
+ )
+
+ # Check the underlying type
+ frame = thread.GetFrameAtIndex(0)
+ kOne8 = frame.GetValueForVariablePath("UnscopedEnumInt8::kOne8")
+ underlying_type = kOne8.GetType().GetEnumerationIntegerType().GetName()
+ self.assertEqual(underlying_type, "int8_t")
diff --git a/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/main.cpp
new file mode 100644
index 0000000000000..6e801da2120bc
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/EnumValueLookup/main.cpp
@@ -0,0 +1,19 @@
+#include <cstdint>
+
+enum UnscopedEnum { kZero, kOne };
+enum UnscopedEnumInt8 : int8_t { kZero8, kOne8 };
+enum class ScopedEnum { kZeroS, kOneS };
+namespace ns {
+enum NSUnscopedEnum { kZeroNS, kOneNS };
+}
+
+void stop() {}
+int main(int argc, char **argv) {
+ auto enum_one = UnscopedEnum::kOne;
+ auto enum_one_8 = UnscopedEnumInt8::kOne8;
+ auto sc_enum_one = ScopedEnum::kOneS;
+ auto ns_enum_one = ns::NSUnscopedEnum::kOneNS;
+
+ stop(); // Set a breakpoint here
+ return 0;
+}
More information about the lldb-commits
mailing list