diff options
10 files changed, 206 insertions, 1 deletions
diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index dc6fe230eb0..051ed7220ac 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -116,6 +116,13 @@ public: bool GetAutoApplyFixIts(); + + bool + GetTopLevel (); + + void + SetTopLevel (bool b = true); + protected: diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index c74e4fe7df1..9189ead43ca 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -260,8 +260,10 @@ class EvaluateExpressionOptions { public: static const uint32_t default_timeout = 500000; + static const ExecutionPolicy default_execution_policy = eExecutionPolicyOnlyWhenNeeded; + EvaluateExpressionOptions() : - m_execution_policy(eExecutionPolicyOnlyWhenNeeded), + m_execution_policy(default_execution_policy), m_language (lldb::eLanguageTypeUnknown), m_prefix (), // A prefix specific to this expression that is added after the prefix from the settings (if any) m_coerce_to_id (false), diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/top-level/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/Makefile new file mode 100644 index 00000000000..7146f227b98 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/Makefile @@ -0,0 +1,12 @@ +LEVEL = ../../make + +default: a.out dummy + +CXX_SOURCES := main.cpp test.cpp + +dummy: dummy.cpp + +clean:: + rm -rf dummy dummy.dSYM + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py new file mode 100644 index 00000000000..f9879b8d958 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py @@ -0,0 +1,83 @@ +""" +Test top-level expressions. +""" + +from __future__ import print_function + + + +import unittest2 + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TopLevelExpressionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.cpp', + '// Set breakpoint here') + self.dummy_line = line_number('dummy.cpp', + '// Set breakpoint here') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + + + def build_and_run(self): + """Test top-level expressions.""" + self.build() + + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + def run_dummy(self): + self.runCmd("file dummy", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "dummy.cpp", self.dummy_line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @add_test_categories(['pyapi']) + def test_top_level_expressions(self): + self.build_and_run() + + resultFromCode = self.frame().EvaluateExpression("doTest()").GetValueAsUnsigned() + + self.runCmd("kill") + + self.run_dummy() + + codeFile = open('test.cpp', 'r') + + expressions = [] + current_expression = "" + + for line in codeFile: + if line.startswith("// --"): + expressions.append(current_expression) + current_expression = "" + else: + current_expression += line + + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + options.SetTopLevel(True) + + for expression in expressions: + self.frame().EvaluateExpression(expression, options) + + resultFromTopLevel = self.frame().EvaluateExpression("doTest()").GetValueAsUnsigned() + + self.assertEqual(resultFromCode, resultFromTopLevel) diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp new file mode 100644 index 00000000000..31204b21d97 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main() +{ + printf("This is a dummy\n"); // Set breakpoint here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp new file mode 100644 index 00000000000..f9b2dd4c6d9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp @@ -0,0 +1,9 @@ +#include <stdio.h> + +extern int doTest(); + +int main() +{ + printf("%d\n", doTest()); // Set breakpoint here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp new file mode 100644 index 00000000000..dfe76a47c26 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp @@ -0,0 +1,63 @@ +class MyClass +{ +public: + int memberResult() + { + return 1; + } + static int staticResult() + { + return 1; + } + int externResult(); +}; + +// -- + +int MyClass::externResult() +{ + return 1; +} + +// -- + +MyClass m; + +// -- + +enum MyEnum { + myEnumOne = 1, + myEnumTwo, + myEnumThree +}; + +// -- + +class AnotherClass +{ +public: + __attribute__ ((always_inline)) int complicatedFunction() + { + struct { + int i; + } s = { 15 }; + + int as[4] = { 2, 3, 4, 5 }; + + for (signed char a : as) + { + s.i -= a; + } + + return s.i; + } +}; + +// -- + +int doTest() +{ + return m.memberResult() + MyClass::staticResult() + m.externResult() + MyEnum::myEnumThree + myEnumOne + AnotherClass().complicatedFunction(); +} + +// -- diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index a7dd721b90a..328a96ef6b5 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -209,6 +209,18 @@ SBExpressionOptions::SetAutoApplyFixIts (bool b) return m_opaque_ap->SetAutoApplyFixIts (b); } +bool +SBExpressionOptions::GetTopLevel () +{ + return m_opaque_ap->GetExecutionPolicy() == eExecutionPolicyTopLevel; +} + +void +SBExpressionOptions::SetTopLevel (bool b) +{ + m_opaque_ap->SetExecutionPolicy(b ? eExecutionPolicyTopLevel : m_opaque_ap->default_execution_policy); +} + EvaluateExpressionOptions * SBExpressionOptions::get() const { diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index fa2be2c9efb..3f550883b29 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -63,6 +63,7 @@ CommandObjectExpression::CommandOptions::g_option_table[] = { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." }, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple FixIt hints will be automatically applied to the expression." }, { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Interpret the expression as top-level definitions rather than code to be immediately executed."} }; uint32_t @@ -149,6 +150,10 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int unwind_on_error = false; ignore_breakpoints = false; break; + + case 'p': + top_level = true; + break; case 'X': { @@ -191,6 +196,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret language = eLanguageTypeUnknown; m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; auto_apply_fixits = eLazyBoolCalculate; + top_level = false; } const OptionDefinition* @@ -315,6 +321,9 @@ CommandObjectExpression::EvaluateExpression(const char *expr, auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false; options.SetAutoApplyFixIts(auto_apply_fixits); + + if (m_command_options.top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); // If there is any chance we are going to stop and want to see // what went wrong with our expression, we should generate debug info diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 9bd0497d27e..4c5bff8e2a9 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -54,6 +54,7 @@ public: // Options table: Required for subclasses of Options. static OptionDefinition g_option_table[]; + bool top_level; bool unwind_on_error; bool ignore_breakpoints; bool show_types; |

