[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