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

via lldb-commits lldb-commits at lists.llvm.org
Thu Feb 13 01:53:19 PST 2025


Author: Michael Buch
Date: 2025-02-13T09:53:17Z
New Revision: 3ad8657ff60b9967235ad65fdb8b767aae0e799d

URL: https://github.com/llvm/llvm-project/commit/3ad8657ff60b9967235ad65fdb8b767aae0e799d
DIFF: https://github.com/llvm/llvm-project/commit/3ad8657ff60b9967235ad65fdb8b767aae0e799d.diff

LOG: [lldb][SBAPI] Add new SBType::GetTemplateParameterValue API (#126901)

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

Added: 
    

Modified: 
    lldb/include/lldb/API/SBTarget.h
    lldb/include/lldb/API/SBType.h
    lldb/include/lldb/API/SBValue.h
    lldb/source/API/SBType.cpp
    lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py
    lldb/test/API/lang/cpp/template-arguments/Makefile
    lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
    lldb/test/API/lang/cpp/template-arguments/main.cpp

Removed: 
    


################################################################################
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..6401d32c85795 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -687,6 +687,42 @@ 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 {};
+
+  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};
+  DataExtractor data;
+  value.GetData(data);
+
+  ExecutionContext exe_ctx;
+  auto target_sp = target.GetSP();
+  if (!target_sp)
+    return {};
+
+  target_sp->CalculateExecutionContext(exe_ctx);
+
+  return ValueObject::CreateValueObjectFromData("value", data, exe_ctx,
+                                                arg->type);
+}
+
 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..f1b3d7a9806fd 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,42 @@ 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>")
+
+        # Can't get template parameter value with invalid target.
+        self.assertFalse(value.GetType().GetTemplateArgumentValue(lldb.SBTarget(), 1))
+
+        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() {}


        


More information about the lldb-commits mailing list