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 <michaelbuc...@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 <michaelbuc...@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. _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits