-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][SBAPI] Add new SBType::GetTemplateParameterValue API #126901
Conversation
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
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesThis patch adds a new API to rdar://144395216 Full diff: https://github.com/llvm/llvm-project/pull/126901.diff 8 Files Affected:
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() {}
|
We now have three APIs to query template parameters: I chose the simpler approach with this patch but happy to reconsider if others feel one way or the other |
@@ -964,6 +964,7 @@ class LLDB_API SBTarget { | |||
friend class SBSection; | |||
friend class SBSourceManager; | |||
friend class SBSymbol; | |||
friend class SBType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was only necessary to get access to SBTarget::GetSP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is completely optional, it just seemed like a good opportunity to advertise my idea for avoiding these random criss-cross friend declarations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, sorry, this is my bad. I didn't mean to imply that it should be done in this patch. I do like this idea, but I think that if we do that, it should be done in a more wider fashion rather than a one-off.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah fair enough, reverted that for now
✅ With the latest revision this PR passed the Python code formatter. |
@@ -446,6 +446,7 @@ class LLDB_API SBValue { | |||
friend class SBModule; | |||
friend class SBTarget; | |||
friend class SBThread; | |||
friend class SBType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was necessary to get access to the SBValue constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could just represent a template parameter as an SBValue instead?
I'm not sure I understand. Do you mean, even for type template template parameters? How would that work? By creating an empty value of the given type? And how would we pass the "kind" of the template parameter? I don't think it makes sense adding it to the SBValue class..
The current implementation seems okay to me, but if we wanted to create something fancier, then I think it'd be best to create a new SB class (SBTypeTemplateParameter?)
lldb/source/API/SBType.cpp
Outdated
DataExtractor data; | ||
value.GetData(data); | ||
|
||
return SBValue(ValueObjectConstResult::Create(target.GetSP().get(), arg->type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about ValueObject::CreateValueObjectFromData
? It looks like it calls the same function underneath, but it seem more correct.
lldb/source/API/SBType.cpp
Outdated
|
||
Scalar value{arg->value}; | ||
|
||
if (!value.IsValid()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this ever be not valid? What would that even mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea we don't need this
@@ -964,6 +964,7 @@ class LLDB_API SBTarget { | |||
friend class SBSection; | |||
friend class SBSourceManager; | |||
friend class SBSymbol; | |||
friend class SBType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is completely optional, it just seemed like a good opportunity to advertise my idea for avoiding these random criss-cross friend declarations.
Yea |
… Scalar::IsValid check
Tried it, let me know if this is what you were imagining or not |
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks okay to me (modulo the friend messup). Given this is a public API and whatnot, it might be a good idea to wait if folks in the US have any thoughts on this.
6a2c0d3
to
2ff8278
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
) 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)
) 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
) 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)
…to-6.1 [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 theTypeSystemClang::GetIntegralTemplateArgument
for this and thus currently only supports integral non-type template parameters. Types like float/double are not supported yet.rdar://144395216