[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