Skip to content

Commit bf10f05

Browse files
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 (cherry picked from commit 3ad8657)
1 parent 10f6ce8 commit bf10f05

File tree

10 files changed

+158
-4
lines changed

10 files changed

+158
-4
lines changed

lldb/bindings/python/static-binding/LLDBWrapPython.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81870,6 +81870,57 @@ SWIGINTERN PyObject *_wrap_SBType_GetTemplateArgumentType(PyObject *self, PyObje
8187081870
}
8187181871

8187281872

81873+
SWIGINTERN PyObject *_wrap_SBType_GetTemplateArgumentValue(PyObject *self, PyObject *args) {
81874+
PyObject *resultobj = 0;
81875+
lldb::SBType *arg1 = (lldb::SBType *) 0 ;
81876+
lldb::SBTarget arg2 ;
81877+
uint32_t arg3 ;
81878+
void *argp1 = 0 ;
81879+
int res1 = 0 ;
81880+
void *argp2 ;
81881+
int res2 = 0 ;
81882+
unsigned int val3 ;
81883+
int ecode3 = 0 ;
81884+
PyObject *swig_obj[3] ;
81885+
lldb::SBValue result;
81886+
81887+
(void)self;
81888+
if (!SWIG_Python_UnpackTuple(args, "SBType_GetTemplateArgumentValue", 3, 3, swig_obj)) SWIG_fail;
81889+
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_lldb__SBType, 0 | 0 );
81890+
if (!SWIG_IsOK(res1)) {
81891+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBType_GetTemplateArgumentValue" "', argument " "1"" of type '" "lldb::SBType *""'");
81892+
}
81893+
arg1 = reinterpret_cast< lldb::SBType * >(argp1);
81894+
{
81895+
res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_lldb__SBTarget, 0 | 0);
81896+
if (!SWIG_IsOK(res2)) {
81897+
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SBType_GetTemplateArgumentValue" "', argument " "2"" of type '" "lldb::SBTarget""'");
81898+
}
81899+
if (!argp2) {
81900+
SWIG_exception_fail(SWIG_NullReferenceError, "invalid null reference " "in method '" "SBType_GetTemplateArgumentValue" "', argument " "2"" of type '" "lldb::SBTarget""'");
81901+
} else {
81902+
lldb::SBTarget * temp = reinterpret_cast< lldb::SBTarget * >(argp2);
81903+
arg2 = *temp;
81904+
if (SWIG_IsNewObj(res2)) delete temp;
81905+
}
81906+
}
81907+
ecode3 = SWIG_AsVal_unsigned_SS_int(swig_obj[2], &val3);
81908+
if (!SWIG_IsOK(ecode3)) {
81909+
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SBType_GetTemplateArgumentValue" "', argument " "3"" of type '" "uint32_t""'");
81910+
}
81911+
arg3 = static_cast< uint32_t >(val3);
81912+
{
81913+
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
81914+
result = (arg1)->GetTemplateArgumentValue(SWIG_STD_MOVE(arg2),arg3);
81915+
SWIG_PYTHON_THREAD_END_ALLOW;
81916+
}
81917+
resultobj = SWIG_NewPointerObj((new lldb::SBValue(result)), SWIGTYPE_p_lldb__SBValue, SWIG_POINTER_OWN | 0 );
81918+
return resultobj;
81919+
fail:
81920+
return NULL;
81921+
}
81922+
81923+
8187381924
SWIGINTERN PyObject *_wrap_SBType_GetTemplateArgumentKind(PyObject *self, PyObject *args) {
8187481925
PyObject *resultobj = 0;
8187581926
lldb::SBType *arg1 = (lldb::SBType *) 0 ;
@@ -100016,6 +100067,7 @@ static PyMethodDef SwigMethods[] = {
100016100067
" * Objective-C: Always returns an invalid SBType.\n"
100017100068
"\n"
100018100069
""},
100070+
{ "SBType_GetTemplateArgumentValue", _wrap_SBType_GetTemplateArgumentValue, METH_VARARGS, "SBType_GetTemplateArgumentValue(SBType self, SBTarget target, uint32_t idx) -> SBValue"},
100019100071
{ "SBType_GetTemplateArgumentKind", _wrap_SBType_GetTemplateArgumentKind, METH_VARARGS, "\n"
100020100072
"SBType_GetTemplateArgumentKind(SBType self, uint32_t idx) -> lldb::TemplateArgumentKind\n"
100021100073
"Returns the kind of the template argument with the given index.\n"

lldb/bindings/python/static-binding/lldb.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14028,6 +14028,10 @@ def GetTemplateArgumentType(self, idx):
1402814028
"""
1402914029
return _lldb.SBType_GetTemplateArgumentType(self, idx)
1403014030

14031+
def GetTemplateArgumentValue(self, target, idx):
14032+
r"""GetTemplateArgumentValue(SBType self, SBTarget target, uint32_t idx) -> SBValue"""
14033+
return _lldb.SBType_GetTemplateArgumentValue(self, target, idx)
14034+
1403114035
def GetTemplateArgumentKind(self, idx):
1403214036
r"""
1403314037
GetTemplateArgumentKind(SBType self, uint32_t idx) -> lldb::TemplateArgumentKind

lldb/include/lldb/API/SBTarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ class LLDB_API SBTarget {
970970
friend class SBSection;
971971
friend class SBSourceManager;
972972
friend class SBSymbol;
973+
friend class SBType;
973974
friend class SBTypeStaticField;
974975
friend class SBValue;
975976
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
@@ -444,6 +444,7 @@ class LLDB_API SBValue {
444444
friend class SBModule;
445445
friend class SBTarget;
446446
friend class SBThread;
447+
friend class SBType;
447448
friend class SBTypeStaticField;
448449
friend class SBTypeSummary;
449450
friend class SBValueList;

lldb/source/API/SBType.cpp

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

707+
lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target,
708+
uint32_t idx) {
709+
LLDB_INSTRUMENT_VA(this, target, idx);
710+
711+
if (!IsValid())
712+
return {};
713+
714+
std::optional<CompilerType::IntegralTemplateArgument> arg;
715+
const bool expand_pack = true;
716+
switch (GetTemplateArgumentKind(idx)) {
717+
case eTemplateArgumentKindIntegral:
718+
arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument(
719+
idx, expand_pack);
720+
break;
721+
default:
722+
break;
723+
}
724+
725+
if (!arg)
726+
return {};
727+
728+
Scalar value{arg->value};
729+
DataExtractor data;
730+
value.GetData(data);
731+
732+
ExecutionContext exe_ctx;
733+
auto target_sp = target.GetSP();
734+
if (!target_sp)
735+
return {};
736+
737+
target_sp->CalculateExecutionContext(exe_ctx);
738+
739+
return ValueObject::CreateValueObjectFromData("value", data, exe_ctx,
740+
arg->type);
741+
}
742+
707743
SBType SBType::FindDirectNestedType(const char *name) {
708744
LLDB_INSTRUMENT_VA(this, name);
709745

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)