summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp21
-rw-r--r--lldb/source/Commands/CommandObjectExpression.h1
-rw-r--r--lldb/test/expression_command/options/Makefile5
-rw-r--r--lldb/test/expression_command/options/TestExprOptions.py100
-rw-r--r--lldb/test/expression_command/options/foo.cpp11
-rw-r--r--lldb/test/expression_command/options/main.cpp15
6 files changed, 146 insertions, 7 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 1be17a0cfdd..56a91f7a91c 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, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." },
{ LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, NULL, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
};
@@ -84,12 +85,11 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
switch (short_option)
{
- //case 'l':
- //if (language.SetLanguageFromCString (option_arg) == false)
- //{
- // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg);
- //}
- //break;
+ case 'l':
+ language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
+ if (language == eLanguageTypeUnknown)
+ error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg);
+ break;
case 'a':
{
@@ -180,6 +180,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
try_all_threads = true;
timeout = 0;
debug = false;
+ language = eLanguageTypeUnknown;
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
}
@@ -192,7 +193,7 @@ CommandObjectExpression::CommandOptions::GetDefinitions ()
CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
CommandObjectRaw (interpreter,
"expression",
- "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
+ "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.",
NULL,
eCommandProcessMustBePaused | eCommandTryTargetAPILock),
IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
@@ -300,6 +301,12 @@ CommandObjectExpression::EvaluateExpression
options.SetTryAllThreads(m_command_options.try_all_threads);
options.SetDebug(m_command_options.debug);
+ // If the language was not specified, set it from target's properties
+ if (m_command_options.language != eLanguageTypeUnknown)
+ options.SetLanguage(m_command_options.language);
+ else
+ options.SetLanguage(target->GetLanguage());
+
// 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
if (!m_command_options.ignore_breakpoints ||
diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h
index 168140d7fe5..7b773bf2d43 100644
--- a/lldb/source/Commands/CommandObjectExpression.h
+++ b/lldb/source/Commands/CommandObjectExpression.h
@@ -61,6 +61,7 @@ public:
bool debug;
uint32_t timeout;
bool try_all_threads;
+ lldb::LanguageType language;
LanguageRuntimeDescriptionDisplayVerbosity m_verbosity;
};
diff --git a/lldb/test/expression_command/options/Makefile b/lldb/test/expression_command/options/Makefile
new file mode 100644
index 00000000000..81ae6f6f16e
--- /dev/null
+++ b/lldb/test/expression_command/options/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp foo.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/expression_command/options/TestExprOptions.py b/lldb/test/expression_command/options/TestExprOptions.py
new file mode 100644
index 00000000000..523463a901b
--- /dev/null
+++ b/lldb/test/expression_command/options/TestExprOptions.py
@@ -0,0 +1,100 @@
+"""
+Test expression command options.
+
+Test cases:
+
+o test_expr_options:
+ Test expression command options.
+"""
+
+import os, time
+import unittest2
+import lldb
+import lldbutil
+from lldbtest import *
+
+class ExprOptionsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ self.main_source = "main.cpp"
+ self.main_source_spec = lldb.SBFileSpec (self.main_source)
+ self.line = line_number('main.cpp', '// breakpoint_in_main')
+ self.exe = os.path.join(os.getcwd(), "a.out")
+
+ def test_expr_options(self):
+ """These expression command options should work as expected."""
+ self.buildDefault()
+
+ # Set debugger into synchronous mode
+ self.dbg.SetAsync(False)
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(self.exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Set breakpoints inside main.
+ breakpoint = target.BreakpointCreateBySourceRegex('// breakpoint_in_main', self.main_source_spec)
+ self.assertTrue(breakpoint)
+
+ # Now launch the process, and do not stop at entry point.
+ process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint)
+ self.assertEqual(len(threads), 1)
+
+ frame = threads[0].GetFrameAtIndex(0)
+ options = lldb.SBExpressionOptions()
+
+ # -- test --language on ObjC builtin type using the SB API's --
+ # Make sure we can evaluate the ObjC builtin type 'id':
+ val = frame.EvaluateExpression('id my_id = 0; my_id')
+ self.assertTrue(val.IsValid())
+ self.assertTrue(val.GetError().Success())
+ self.assertEqual(val.GetValueAsUnsigned(0), 0)
+ self.DebugSBValue(val)
+
+ # Make sure it still works if language is set to ObjC:
+ options.SetLanguage(lldb.eLanguageTypeObjC)
+ val = frame.EvaluateExpression('id my_id = 0; my_id', options)
+ self.assertTrue(val.IsValid())
+ self.assertTrue(val.GetError().Success())
+ self.assertEqual(val.GetValueAsUnsigned(0), 0)
+ self.DebugSBValue(val)
+
+ # Make sure it fails if language is set to C:
+ options.SetLanguage(lldb.eLanguageTypeC)
+ val = frame.EvaluateExpression('id my_id = 0; my_id', options)
+ self.assertTrue(val.IsValid())
+ self.assertFalse(val.GetError().Success())
+
+ # -- test --language on C++ expression using the SB API's --
+ # Make sure we can evaluate 'ns::func'.
+ val = frame.EvaluateExpression('ns::func')
+ self.assertTrue(val.IsValid())
+ self.assertTrue(val.GetError().Success())
+ self.DebugSBValue(val)
+
+ # Make sure it still works if language is set to C++:
+ options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
+ val = frame.EvaluateExpression('ns::func', options)
+ self.assertTrue(val.IsValid())
+ self.assertTrue(val.GetError().Success())
+ self.DebugSBValue(val)
+
+ # Make sure it fails if language is set to C:
+ options.SetLanguage(lldb.eLanguageTypeC)
+ val = frame.EvaluateExpression('ns::func', options)
+ self.assertTrue(val.IsValid())
+ self.assertFalse(val.GetError().Success())
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/expression_command/options/foo.cpp b/lldb/test/expression_command/options/foo.cpp
new file mode 100644
index 00000000000..8a5a6a2b541
--- /dev/null
+++ b/lldb/test/expression_command/options/foo.cpp
@@ -0,0 +1,11 @@
+namespace ns {
+ int func(void)
+ {
+ return 0;
+ }
+}
+
+extern "C" int foo(void)
+{
+ return ns::func();
+}
diff --git a/lldb/test/expression_command/options/main.cpp b/lldb/test/expression_command/options/main.cpp
new file mode 100644
index 00000000000..ecd9a90f662
--- /dev/null
+++ b/lldb/test/expression_command/options/main.cpp
@@ -0,0 +1,15 @@
+extern "C" int foo(void);
+static int static_value = 0;
+
+int
+bar()
+{
+ static_value++;
+ return static_value;
+}
+
+int main (int argc, char const *argv[])
+{
+ bar(); // breakpoint_in_main
+ return foo();
+}
OpenPOWER on IntegriCloud