[Lldb-commits] [lldb] [lldb][SBAPI] Add new SBType::GetTemplateParameterValue API (PR #126901)

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 12 04:39:57 PST 2025


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/126901

>From d69bd14f285f5508abc35b60172efc8839b7c0fd Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 12 Feb 2025 12:27:22 +0000
Subject: [PATCH 1/2] [lldb][SBAPI] Add new SBType::GetTemplateParameterValue
 API

This patch adds a new API to `SBType` to retrieve the value of a
template parameter given an index. We re-use the
`TypeSystemClang::GetIntegralTemplateArgument` for this and thus currently only supports integral non-type template parameters. Types like float/double are not supported yet.

rdar://144395216
---
 lldb/include/lldb/API/SBTarget.h              |  1 +
 lldb/include/lldb/API/SBType.h                |  7 ++++
 lldb/include/lldb/API/SBValue.h               |  1 +
 lldb/source/API/SBType.cpp                    | 34 +++++++++++++++++++
 .../TestTemplatePackArgs.py                   | 19 +++++++++--
 .../API/lang/cpp/template-arguments/Makefile  |  1 +
 .../TestCppTemplateArguments.py               | 32 +++++++++++++++--
 .../API/lang/cpp/template-arguments/main.cpp  |  5 +++
 8 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index 9b97359d49cf9..bb912ab41d0fe 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -964,6 +964,7 @@ class LLDB_API SBTarget {
   friend class SBSection;
   friend class SBSourceManager;
   friend class SBSymbol;
+  friend class SBType;
   friend class SBTypeStaticField;
   friend class SBValue;
   friend class SBVariablesOptions;
diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h
index 63ba91082d576..9ad3244686328 100644
--- a/lldb/include/lldb/API/SBType.h
+++ b/lldb/include/lldb/API/SBType.h
@@ -221,6 +221,13 @@ class SBType {
 
   lldb::SBType GetTemplateArgumentType(uint32_t idx);
 
+  /// Returns the value of the non-type template parameter at index \c idx.
+  /// If \c idx is out-of-bounds or the template parameter doesn't have
+  /// a value, returns an empty SBValue.
+  ///
+  /// This function will expand parameter packs.
+  lldb::SBValue GetTemplateArgumentValue(lldb::SBTarget target, uint32_t idx);
+
   /// Return the TemplateArgumentKind of the template argument at index idx.
   /// Variadic argument packs are automatically expanded.
   lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx);
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index 9090cece80f7c..46ef6daa95264 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -446,6 +446,7 @@ class LLDB_API SBValue {
   friend class SBModule;
   friend class SBTarget;
   friend class SBThread;
+  friend class SBType;
   friend class SBTypeStaticField;
   friend class SBTypeSummary;
   friend class SBValueList;
diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index 4cc16c64e4756..8d04e9650b781 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -687,6 +687,40 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
   return eTemplateArgumentKindNull;
 }
 
+lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
+                                               uint32_t idx) {
+  LLDB_INSTRUMENT_VA(this, target, idx);
+
+  if (!IsValid())
+    return SBValue();
+
+  std::optional<CompilerType::IntegralTemplateArgument> arg;
+  const bool expand_pack = true;
+  switch (GetTemplateArgumentKind(idx)) {
+  case eTemplateArgumentKindIntegral:
+    arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument(
+        idx, expand_pack);
+    break;
+  default:
+    break;
+  }
+
+  if (!arg)
+    return {};
+
+  Scalar value{arg->value};
+
+  if (!value.IsValid())
+    return {};
+
+  DataExtractor data;
+  value.GetData(data);
+
+  auto value_obj_sp = ValueObjectConstResult::Create(
+      target.GetSP().get(), arg->type, ConstString("value"), data);
+  return SBValue(std::move(value_obj_sp));
+}
+
 SBType SBType::FindDirectNestedType(const char *name) {
   LLDB_INSTRUMENT_VA(this, name);
 
diff --git a/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py b/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py
index c571357ff6720..f2467cbea9439 100644
--- a/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py
+++ b/lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py
@@ -11,7 +11,7 @@
 class TemplatePackArgsTestCase(TestBase):
     def test_template_argument_pack(self):
         self.build()
-        (_, _, thread, _) = lldbutil.run_to_source_breakpoint(
+        (target, _, thread, _) = lldbutil.run_to_source_breakpoint(
             self, "breakpoint here", lldb.SBFileSpec("main.cpp"), exe_name="a.out"
         )
         frame = thread.GetSelectedFrame()
@@ -33,10 +33,25 @@ def test_template_argument_pack(self):
         self.assertEqual(
             only_pack.GetType().GetTemplateArgumentType(2).GetName(), "double"
         )
-        # Access the C<double, 42> template parameter.
+
         nested_template = only_pack.GetType().GetTemplateArgumentType(3)
         self.assertEqual(nested_template.GetName(), "D<int, int, bool>")
         self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3)
         self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), "int")
         self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), "int")
         self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), "bool")
+
+        my_c = frame.FindVariable("myC")
+        self.assertTrue(my_c.IsValid(), "make sure we find the myC variable")
+
+        # Out of bounds index.
+        self.assertFalse(my_c.GetType().GetTemplateArgumentValue(target, 3))
+
+        # Out of bounds index.
+        template_param_value = my_c.GetType().GetTemplateArgumentValue(target, 1)
+        self.assertEqual(template_param_value.GetTypeName(), "int")
+        self.assertEqual(template_param_value.GetValueAsSigned(), 16)
+
+        template_param_value = my_c.GetType().GetTemplateArgumentValue(target, 2)
+        self.assertEqual(template_param_value.GetTypeName(), "int")
+        self.assertEqual(template_param_value.GetValueAsSigned(), 32)
diff --git a/lldb/test/API/lang/cpp/template-arguments/Makefile b/lldb/test/API/lang/cpp/template-arguments/Makefile
index 99998b20bcb05..4f79c0a900c3a 100644
--- a/lldb/test/API/lang/cpp/template-arguments/Makefile
+++ b/lldb/test/API/lang/cpp/template-arguments/Makefile
@@ -1,3 +1,4 @@
 CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -std=c++20
 
 include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
index 7b63a6cca8db4..eb5959c2a3668 100644
--- a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
+++ b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
@@ -8,7 +8,7 @@ class TestCase(TestBase):
     @no_debug_info_test
     def test(self):
         self.build()
-        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
 
         value = self.expect_expr("temp1", result_type="C<int, 2>")
         template_type = value.GetType()
@@ -27,10 +27,38 @@ def test(self):
         self.assertEqual(
             template_type.GetTemplateArgumentType(1).GetName(), "unsigned int"
         )
-        # FIXME: There is no way to get the actual value of the parameter.
+
+        # Template parameter isn't a NTTP.
+        self.assertFalse(template_type.GetTemplateArgumentValue(target, 0))
+
+        # Template parameter index out-of-bounds.
+        self.assertFalse(template_type.GetTemplateArgumentValue(target, 2))
+
+        # Template parameter is a NTTP.
+        param_val = template_type.GetTemplateArgumentValue(target, 1)
+        self.assertEqual(param_val.GetTypeName(), "unsigned int")
+        self.assertEqual(param_val.GetValueAsUnsigned(), 2)
 
         # Try to get an invalid template argument.
         self.assertEqual(
             template_type.GetTemplateArgumentKind(2), lldb.eTemplateArgumentKindNull
         )
         self.assertEqual(template_type.GetTemplateArgumentType(2).GetName(), "")
+
+        value = self.expect_expr("temp2", result_type="Foo<short, -2>")
+        template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
+        self.assertTrue(template_param_value)
+        self.assertEqual(template_param_value.GetTypeName(), "short")
+        self.assertEqual(template_param_value.GetValueAsSigned(), -2)
+
+        value = self.expect_expr("temp3", result_type="Foo<char, 'v'>")
+        template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
+        self.assertTrue(template_param_value)
+        self.assertEqual(template_param_value.GetTypeName(), "char")
+        self.assertEqual(chr(template_param_value.GetValueAsSigned()), 'v')
+
+        # FIXME: type should be Foo<float, 2.0f>
+        # FIXME: double/float NTTP parameter values currently not supported.
+        value = self.expect_expr("temp4", result_type="Foo<float, float>")
+        template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
+        self.assertFalse(template_param_value)
diff --git a/lldb/test/API/lang/cpp/template-arguments/main.cpp b/lldb/test/API/lang/cpp/template-arguments/main.cpp
index 728bd400c2586..0c0eb97cbc858 100644
--- a/lldb/test/API/lang/cpp/template-arguments/main.cpp
+++ b/lldb/test/API/lang/cpp/template-arguments/main.cpp
@@ -5,4 +5,9 @@ struct C {
 
 C<int, 2> temp1;
 
+template <typename T, T value> struct Foo {};
+Foo<short, -2> temp2;
+Foo<char, 'v'> temp3;
+Foo<float, 2.0f> temp4;
+
 int main() {}

>From 09205d7d4a28bfcecfb6bfe544c89cba34a6c4c6 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 12 Feb 2025 12:38:31 +0000
Subject: [PATCH 2/2] fixup! formatting

---
 lldb/source/API/SBType.cpp                                 | 7 +++----
 .../cpp/template-arguments/TestCppTemplateArguments.py     | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index 8d04e9650b781..bedddd4b4f14b 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -692,7 +692,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
   LLDB_INSTRUMENT_VA(this, target, idx);
 
   if (!IsValid())
-    return SBValue();
+    return {};
 
   std::optional<CompilerType::IntegralTemplateArgument> arg;
   const bool expand_pack = true;
@@ -716,9 +716,8 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
   DataExtractor data;
   value.GetData(data);
 
-  auto value_obj_sp = ValueObjectConstResult::Create(
-      target.GetSP().get(), arg->type, ConstString("value"), data);
-  return SBValue(std::move(value_obj_sp));
+  return SBValue(ValueObjectConstResult::Create(target.GetSP().get(), arg->type,
+                                                ConstString("value"), data));
 }
 
 SBType SBType::FindDirectNestedType(const char *name) {
diff --git a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
index eb5959c2a3668..f2c0a409d0980 100644
--- a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
+++ b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
@@ -55,7 +55,7 @@ def test(self):
         template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
         self.assertTrue(template_param_value)
         self.assertEqual(template_param_value.GetTypeName(), "char")
-        self.assertEqual(chr(template_param_value.GetValueAsSigned()), 'v')
+        self.assertEqual(chr(template_param_value.GetValueAsSigned()), "v")
 
         # FIXME: type should be Foo<float, 2.0f>
         # FIXME: double/float NTTP parameter values currently not supported.



More information about the lldb-commits mailing list