[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 05:21:14 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/3] [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/3] 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.
>From 2ff8278dcff2b85be42cd890471ccb88bc19835f Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 12 Feb 2025 13:20:36 +0000
Subject: [PATCH 3/3] fixup! use CreateValueObjectFromData; add test-case;
remove redundant Scalar::IsValid check
---
lldb/source/API/SBType.cpp | 13 ++++++++-----
.../template-arguments/TestCppTemplateArguments.py | 4 ++++
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index bedddd4b4f14b..6401d32c85795 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -709,15 +709,18 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
return {};
Scalar value{arg->value};
+ DataExtractor data;
+ value.GetData(data);
- if (!value.IsValid())
+ ExecutionContext exe_ctx;
+ auto target_sp = target.GetSP();
+ if (!target_sp)
return {};
- DataExtractor data;
- value.GetData(data);
+ target_sp->CalculateExecutionContext(exe_ctx);
- return SBValue(ValueObjectConstResult::Create(target.GetSP().get(), arg->type,
- ConstString("value"), data));
+ return ValueObject::CreateValueObjectFromData("value", data, exe_ctx,
+ arg->type);
}
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 f2c0a409d0980..f1b3d7a9806fd 100644
--- a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
+++ b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
@@ -46,6 +46,10 @@ def test(self):
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")
More information about the lldb-commits
mailing list