Skip to content

Commit 5644c70

Browse files
Michael137joaosaffran
authored and
joaosaffran
committed
[lldb][SBAPI] Add new SBType::GetTemplateParameterValue API (llvm#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
1 parent 902d415 commit 5644c70

File tree

8 files changed

+102
-4
lines changed

8 files changed

+102
-4
lines changed

lldb/include/lldb/API/SBTarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ class LLDB_API SBTarget {
964964
friend class SBSection;
965965
friend class SBSourceManager;
966966
friend class SBSymbol;
967+
friend class SBType;
967968
friend class SBTypeStaticField;
968969
friend class SBValue;
969970
friend class SBVariablesOptions;

lldb/include/lldb/API/SBType.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ class SBType {
221221

222222
lldb::SBType GetTemplateArgumentType(uint32_t idx);
223223

224+
/// Returns the value of the non-type template parameter at index \c idx.
225+
/// If \c idx is out-of-bounds or the template parameter doesn't have
226+
/// a value, returns an empty SBValue.
227+
///
228+
/// This function will expand parameter packs.
229+
lldb::SBValue GetTemplateArgumentValue(lldb::SBTarget target, uint32_t idx);
230+
224231
/// Return the TemplateArgumentKind of the template argument at index idx.
225232
/// Variadic argument packs are automatically expanded.
226233
lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx);

lldb/include/lldb/API/SBValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ class LLDB_API SBValue {
446446
friend class SBModule;
447447
friend class SBTarget;
448448
friend class SBThread;
449+
friend class SBType;
449450
friend class SBTypeStaticField;
450451
friend class SBTypeSummary;
451452
friend class SBValueList;

lldb/source/API/SBType.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,42 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
687687
return eTemplateArgumentKindNull;
688688
}
689689

690+
lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
691+
uint32_t idx) {
692+
LLDB_INSTRUMENT_VA(this, target, idx);
693+
694+
if (!IsValid())
695+
return {};
696+
697+
std::optional<CompilerType::IntegralTemplateArgument> arg;
698+
const bool expand_pack = true;
699+
switch (GetTemplateArgumentKind(idx)) {
700+
case eTemplateArgumentKindIntegral:
701+
arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument(
702+
idx, expand_pack);
703+
break;
704+
default:
705+
break;
706+
}
707+
708+
if (!arg)
709+
return {};
710+
711+
Scalar value{arg->value};
712+
DataExtractor data;
713+
value.GetData(data);
714+
715+
ExecutionContext exe_ctx;
716+
auto target_sp = target.GetSP();
717+
if (!target_sp)
718+
return {};
719+
720+
target_sp->CalculateExecutionContext(exe_ctx);
721+
722+
return ValueObject::CreateValueObjectFromData("value", data, exe_ctx,
723+
arg->type);
724+
}
725+
690726
SBType SBType::FindDirectNestedType(const char *name) {
691727
LLDB_INSTRUMENT_VA(this, name);
692728

lldb/test/API/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class TemplatePackArgsTestCase(TestBase):
1212
def test_template_argument_pack(self):
1313
self.build()
14-
(_, _, thread, _) = lldbutil.run_to_source_breakpoint(
14+
(target, _, thread, _) = lldbutil.run_to_source_breakpoint(
1515
self, "breakpoint here", lldb.SBFileSpec("main.cpp"), exe_name="a.out"
1616
)
1717
frame = thread.GetSelectedFrame()
@@ -33,10 +33,25 @@ def test_template_argument_pack(self):
3333
self.assertEqual(
3434
only_pack.GetType().GetTemplateArgumentType(2).GetName(), "double"
3535
)
36-
# Access the C<double, 42> template parameter.
36+
3737
nested_template = only_pack.GetType().GetTemplateArgumentType(3)
3838
self.assertEqual(nested_template.GetName(), "D<int, int, bool>")
3939
self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3)
4040
self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), "int")
4141
self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), "int")
4242
self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), "bool")
43+
44+
my_c = frame.FindVariable("myC")
45+
self.assertTrue(my_c.IsValid(), "make sure we find the myC variable")
46+
47+
# Out of bounds index.
48+
self.assertFalse(my_c.GetType().GetTemplateArgumentValue(target, 3))
49+
50+
# Out of bounds index.
51+
template_param_value = my_c.GetType().GetTemplateArgumentValue(target, 1)
52+
self.assertEqual(template_param_value.GetTypeName(), "int")
53+
self.assertEqual(template_param_value.GetValueAsSigned(), 16)
54+
55+
template_param_value = my_c.GetType().GetTemplateArgumentValue(target, 2)
56+
self.assertEqual(template_param_value.GetTypeName(), "int")
57+
self.assertEqual(template_param_value.GetValueAsSigned(), 32)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CXX_SOURCES := main.cpp
2+
CXXFLAGS_EXTRAS := -std=c++20
23

34
include Makefile.rules

lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class TestCase(TestBase):
88
@no_debug_info_test
99
def test(self):
1010
self.build()
11-
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
11+
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
1212

1313
value = self.expect_expr("temp1", result_type="C<int, 2>")
1414
template_type = value.GetType()
@@ -27,10 +27,42 @@ def test(self):
2727
self.assertEqual(
2828
template_type.GetTemplateArgumentType(1).GetName(), "unsigned int"
2929
)
30-
# FIXME: There is no way to get the actual value of the parameter.
30+
31+
# Template parameter isn't a NTTP.
32+
self.assertFalse(template_type.GetTemplateArgumentValue(target, 0))
33+
34+
# Template parameter index out-of-bounds.
35+
self.assertFalse(template_type.GetTemplateArgumentValue(target, 2))
36+
37+
# Template parameter is a NTTP.
38+
param_val = template_type.GetTemplateArgumentValue(target, 1)
39+
self.assertEqual(param_val.GetTypeName(), "unsigned int")
40+
self.assertEqual(param_val.GetValueAsUnsigned(), 2)
3141

3242
# Try to get an invalid template argument.
3343
self.assertEqual(
3444
template_type.GetTemplateArgumentKind(2), lldb.eTemplateArgumentKindNull
3545
)
3646
self.assertEqual(template_type.GetTemplateArgumentType(2).GetName(), "")
47+
48+
value = self.expect_expr("temp2", result_type="Foo<short, -2>")
49+
50+
# Can't get template parameter value with invalid target.
51+
self.assertFalse(value.GetType().GetTemplateArgumentValue(lldb.SBTarget(), 1))
52+
53+
template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
54+
self.assertTrue(template_param_value)
55+
self.assertEqual(template_param_value.GetTypeName(), "short")
56+
self.assertEqual(template_param_value.GetValueAsSigned(), -2)
57+
58+
value = self.expect_expr("temp3", result_type="Foo<char, 'v'>")
59+
template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
60+
self.assertTrue(template_param_value)
61+
self.assertEqual(template_param_value.GetTypeName(), "char")
62+
self.assertEqual(chr(template_param_value.GetValueAsSigned()), "v")
63+
64+
# FIXME: type should be Foo<float, 2.0f>
65+
# FIXME: double/float NTTP parameter values currently not supported.
66+
value = self.expect_expr("temp4", result_type="Foo<float, float>")
67+
template_param_value = value.GetType().GetTemplateArgumentValue(target, 1)
68+
self.assertFalse(template_param_value)

lldb/test/API/lang/cpp/template-arguments/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ struct C {
55

66
C<int, 2> temp1;
77

8+
template <typename T, T value> struct Foo {};
9+
Foo<short, -2> temp2;
10+
Foo<char, 'v'> temp3;
11+
Foo<float, 2.0f> temp4;
12+
813
int main() {}

0 commit comments

Comments
 (0)