From 6a85b9d16387ddd7c356336c8a77ba6b88f9a610 Mon Sep 17 00:00:00 2001 From: Emre Kultursay Date: Tue, 21 Jun 2022 14:28:53 +0200 Subject: [PATCH] Support expressions in the context of a reference ...type variable by dereferencing the variable before evaluating the expression. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D128126 --- lldb/source/Expression/UserExpression.cpp | 20 +++++++- .../expression/context-object/TestContextObject.py | 54 +++++++++++----------- .../commands/expression/context-object/main.cpp | 3 ++ 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index fd26cbd..f821603 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -145,8 +145,9 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step)); if (ctx_obj) { - static unsigned const ctx_type_mask = - lldb::TypeFlags::eTypeIsClass | lldb::TypeFlags::eTypeIsStructUnion; + static unsigned const ctx_type_mask = lldb::TypeFlags::eTypeIsClass | + lldb::TypeFlags::eTypeIsStructUnion | + lldb::TypeFlags::eTypeIsReference; if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) { LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of " "an invalid type, can't run expressions."); @@ -155,6 +156,21 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } } + if (ctx_obj && ctx_obj->GetTypeInfo() & lldb::TypeFlags::eTypeIsReference) { + Status error; + lldb::ValueObjectSP deref_ctx_sp = ctx_obj->Dereference(error); + if (!error.Success()) { + LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of " + "a reference type that can't be dereferenced, can't run " + "expressions."); + error.SetErrorString( + "passed context object of an reference type cannot be deferenced"); + return lldb::eExpressionSetupError; + } + + ctx_obj = deref_ctx_sp.get(); + } + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() diff --git a/lldb/test/API/commands/expression/context-object/TestContextObject.py b/lldb/test/API/commands/expression/context-object/TestContextObject.py index a53cbac..45f7a00 100644 --- a/lldb/test/API/commands/expression/context-object/TestContextObject.py +++ b/lldb/test/API/commands/expression/context-object/TestContextObject.py @@ -16,34 +16,34 @@ class ContextObjectTestCase(TestBase): frame = thread.GetFrameAtIndex(0) # - # Test C++ struct variable + # Test C++ struct variable and reference-to-struct variable # - - obj_val = frame.FindVariable("cpp_struct") - self.assertTrue(obj_val.IsValid()) - - # Test an empty expression evaluation - value = obj_val.EvaluateExpression("") - self.assertFalse(value.IsValid()) - self.assertFalse(value.GetError().Success()) - - # Test retrieveing of a field (not a local with the same name) - value = obj_val.EvaluateExpression("field") - self.assertTrue(value.IsValid()) - self.assertSuccess(value.GetError()) - self.assertEqual(value.GetValueAsSigned(), 1111) - - # Test functions evaluation - value = obj_val.EvaluateExpression("function()") - self.assertTrue(value.IsValid()) - self.assertSuccess(value.GetError()) - self.assertEqual(value.GetValueAsSigned(), 2222) - - # Test that we retrieve the right global - value = obj_val.EvaluateExpression("global.field") - self.assertTrue(value.IsValid()) - self.assertSuccess(value.GetError()) - self.assertEqual(value.GetValueAsSigned(), 1111) + for obj in "cpp_struct", "cpp_struct_ref": + obj_val = frame.FindVariable(obj) + self.assertTrue(obj_val.IsValid()) + + # Test an empty expression evaluation + value = obj_val.EvaluateExpression("") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieveing of a field (not a local with the same name) + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertSuccess(value.GetError()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # Test functions evaluation + value = obj_val.EvaluateExpression("function()") + self.assertTrue(value.IsValid()) + self.assertSuccess(value.GetError()) + self.assertEqual(value.GetValueAsSigned(), 2222) + + # Test that we retrieve the right global + value = obj_val.EvaluateExpression("global.field") + self.assertTrue(value.IsValid()) + self.assertSuccess(value.GetError()) + self.assertEqual(value.GetValueAsSigned(), 1111) # # Test C++ union variable diff --git a/lldb/test/API/commands/expression/context-object/main.cpp b/lldb/test/API/commands/expression/context-object/main.cpp index 098b608..4306e95 100644 --- a/lldb/test/API/commands/expression/context-object/main.cpp +++ b/lldb/test/API/commands/expression/context-object/main.cpp @@ -31,6 +31,9 @@ int main() cpp_namespace::CppStruct cpp_struct = cpp_namespace::GetCppStruct(); cpp_struct.function(); + cpp_namespace::CppStruct &cpp_struct_ref = cpp_struct; + cpp_struct_ref.function(); + int field = 4444; cpp_namespace::CppUnion cpp_union; -- 2.7.4