Index: lldb/trunk/source/Commands/CommandObjectExpression.h =================================================================== --- lldb/trunk/source/Commands/CommandObjectExpression.h +++ lldb/trunk/source/Commands/CommandObjectExpression.h @@ -61,6 +61,7 @@ bool debug; uint32_t timeout; bool try_all_threads; + lldb::LanguageType language; LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; }; Index: lldb/trunk/source/Commands/CommandObjectExpression.cpp =================================================================== --- lldb/trunk/source/Commands/CommandObjectExpression.cpp +++ lldb/trunk/source/Commands/CommandObjectExpression.cpp @@ -63,6 +63,7 @@ { 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 @@ 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 @@ try_all_threads = true; timeout = 0; debug = false; + language = eLanguageTypeUnknown; m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; } @@ -192,7 +193,7 @@ 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 @@ 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 || Index: lldb/trunk/test/expression_command/options/Makefile =================================================================== --- lldb/trunk/test/expression_command/options/Makefile +++ lldb/trunk/test/expression_command/options/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp foo.cpp + +include $(LEVEL)/Makefile.rules Index: lldb/trunk/test/expression_command/options/TestExprOptions.py =================================================================== --- lldb/trunk/test/expression_command/options/TestExprOptions.py +++ lldb/trunk/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() Index: lldb/trunk/test/expression_command/options/foo.cpp =================================================================== --- lldb/trunk/test/expression_command/options/foo.cpp +++ lldb/trunk/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(); +} Index: lldb/trunk/test/expression_command/options/main.cpp =================================================================== --- lldb/trunk/test/expression_command/options/main.cpp +++ lldb/trunk/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(); +}