summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBExpressionOptions.h7
-rw-r--r--lldb/include/lldb/Target/Target.h4
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/top-level/Makefile12
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py83
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp7
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp9
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp63
-rw-r--r--lldb/source/API/SBExpressionOptions.cpp12
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp9
-rw-r--r--lldb/source/Commands/CommandObjectExpression.h1
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;
OpenPOWER on IntegriCloud