[Lldb-commits] [lldb] r246829 - Set the default language to use when evaluating to that of the frame's CU.

Dawn Perchik via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 3 18:02:30 PDT 2015


Author: dperchik
Date: Thu Sep  3 20:02:30 2015
New Revision: 246829

URL: http://llvm.org/viewvc/llvm-project?rev=246829&view=rev
Log:
Set the default language to use when evaluating to that of the frame's CU.

* Use the frame's context (instead of just the target's) when evaluating,
  so that the language of the frame's CU can be used to select the
  compiler and/or compiler options to use when parsing the expression.
  This allows for modules built with mixed languages to be parsed in
  the context of their frame. 
* Add all C and C++ language variants when determining the language options
  to set.
* Enable C++ language options when language is C or ObjC as a workaround since
  the expression parser uses features of C++ to capture values.
* Enable ObjC language options when language is C++ as a workaround for ObjC
  requirements.
* Disable C++11 language options when language is C++03.
* Add test TestMixedLanguages.py to check that the language being used
  for evaluation is that of the frame.
* Fix test TestExprOptions.py to check for C++11 instead of C++ since C++ has
  to be enabled for C, and remove redundant expr --language test for ObjC.
* Fix TestPersistentPtrUpdate.py to not require C++11 in C.

Reviewed by: clayborg, spyffe, jingham
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D11102

Added:
    lldb/trunk/test/lang/mixed/
    lldb/trunk/test/lang/mixed/Makefile
    lldb/trunk/test/lang/mixed/TestMixedLanguages.py
    lldb/trunk/test/lang/mixed/foo.cpp
    lldb/trunk/test/lang/mixed/main.c
Modified:
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/ClangExpressionParser.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/test/expression_command/options/TestExprOptions.py
    lldb/trunk/test/expression_command/persistent_ptr_update/TestPersistentPtrUpdate.py

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Thu Sep  3 20:02:30 2015
@@ -466,6 +466,16 @@ public:
     TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
 
     //------------------------------------------------------------------
+    /// Query this frame to determine what the default language should be
+    /// when parsing expressions given the execution context.
+    ///
+    /// @return
+    ///   The language of the frame if known, else lldb::eLanguageTypeUnknown.
+    //------------------------------------------------------------------
+    lldb::LanguageType
+    GetLanguage ();
+
+    //------------------------------------------------------------------
     // lldb::ExecutionContextScope pure virtual functions
     //------------------------------------------------------------------
     lldb::TargetSP

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Sep  3 20:02:30 2015
@@ -289,8 +289,8 @@ CommandObjectExpression::EvaluateExpress
     if (target)
     {
         lldb::ValueObjectSP result_valobj_sp;
-
         bool keep_in_memory = true;
+        StackFrame *frame = exe_ctx.GetFramePtr();
 
         EvaluateExpressionOptions options;
         options.SetCoerceToId(m_varobj_options.use_objc);
@@ -301,11 +301,15 @@ CommandObjectExpression::EvaluateExpress
         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 the language was not specified in the expression command,
+        // set it to the language in the target's properties if
+        // specified, else default to the langage for the frame.
         if (m_command_options.language != eLanguageTypeUnknown)
             options.SetLanguage(m_command_options.language);
-        else
+        else if (target->GetLanguage() != eLanguageTypeUnknown)
             options.SetLanguage(target->GetLanguage());
+        else if (frame)
+            options.SetLanguage(frame->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
@@ -318,8 +322,7 @@ CommandObjectExpression::EvaluateExpress
         else
             options.SetTimeoutUsec(0);
 
-        target->EvaluateExpression(expr, exe_ctx.GetFramePtr(),
-                                   result_valobj_sp, options);
+        target->EvaluateExpression(expr, frame, result_valobj_sp, options);
 
         if (result_valobj_sp)
         {

Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Thu Sep  3 20:02:30 2015
@@ -210,17 +210,38 @@ ClangExpressionParser::ClangExpressionPa
     switch (language)
     {
     case lldb::eLanguageTypeC:
+    case lldb::eLanguageTypeC89:
+    case lldb::eLanguageTypeC99:
+    case lldb::eLanguageTypeC11:
+        // FIXME: the following language option is a temporary workaround,
+        // to "ask for C, get C++."
+        // For now, the expression parser must use C++ anytime the
+        // language is a C family language, because the expression parser
+        // uses features of C++ to capture values.
+        m_compiler->getLangOpts().CPlusPlus = true;
         break;
     case lldb::eLanguageTypeObjC:
         m_compiler->getLangOpts().ObjC1 = true;
         m_compiler->getLangOpts().ObjC2 = true;
+        // FIXME: the following language option is a temporary workaround,
+        // to "ask for ObjC, get ObjC++" (see comment above).
+        m_compiler->getLangOpts().CPlusPlus = true;
         break;
     case lldb::eLanguageTypeC_plus_plus:
-        m_compiler->getLangOpts().CPlusPlus = true;
+    case lldb::eLanguageTypeC_plus_plus_11:
+    case lldb::eLanguageTypeC_plus_plus_14:
         m_compiler->getLangOpts().CPlusPlus11 = true;
         m_compiler->getHeaderSearchOpts().UseLibcxx = true;
+        // fall thru ...
+    case lldb::eLanguageTypeC_plus_plus_03:
+        m_compiler->getLangOpts().CPlusPlus = true;
+        // FIXME: the following language option is a temporary workaround,
+        // to "ask for C++, get ObjC++".  Apple hopes to remove this requirement
+        // on non-Apple platforms, but for now it is needed.
+        m_compiler->getLangOpts().ObjC1 = true;
         break;
     case lldb::eLanguageTypeObjC_plus_plus:
+    case lldb::eLanguageTypeUnknown:
     default:
         m_compiler->getLangOpts().ObjC1 = true;
         m_compiler->getLangOpts().ObjC2 = true;

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Thu Sep  3 20:02:30 2015
@@ -1316,6 +1316,15 @@ StackFrame::IsInlined ()
     return false;
 }
 
+lldb::LanguageType
+StackFrame::GetLanguage ()
+{
+    CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
+    if (cu)
+        return cu->GetLanguage();
+    return lldb::eLanguageTypeUnknown;
+}
+
 TargetSP
 StackFrame::CalculateTarget ()
 {

Modified: lldb/trunk/test/expression_command/options/TestExprOptions.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/options/TestExprOptions.py?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/test/expression_command/options/TestExprOptions.py (original)
+++ lldb/trunk/test/expression_command/options/TestExprOptions.py Thu Sep  3 20:02:30 2015
@@ -26,15 +26,7 @@ class ExprOptionsTestCase(TestBase):
         self.line = line_number('main.cpp', '// breakpoint_in_main')
         self.exe = os.path.join(os.getcwd(), "a.out")
 
-    @skipUnlessDarwin
-    def test_expr_options_objc_cpp(self):
-        self.expr_options(test_objc = True, test_cpp = True)
-
-    @skipIfDarwin # Already covered by test_expr_options_objc_cpp
-    def test_expr_options_cpp(self):
-        self.expr_options(test_objc = False, test_cpp = True)
-
-    def expr_options(self, test_objc, test_cpp):
+    def test_expr_options(self):
         """These expression command options should work as expected."""
         self.buildDefault()
 
@@ -59,49 +51,26 @@ class ExprOptionsTestCase(TestBase):
         frame = threads[0].GetFrameAtIndex(0)
         options = lldb.SBExpressionOptions()
 
-        if test_objc:
-            # -- 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_plus_plus)
-            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())
-
-        if test_cpp:
-            # -- 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())
+        # test --language on C++ expression using the SB API's
+
+        # Make sure we can evaluate 'ns::func'.
+        val = frame.EvaluateExpression('foo != nullptr')
+        self.assertTrue(val.IsValid())
+        self.assertTrue(val.GetError().Success())
+        self.DebugSBValue(val)
+
+        # Make sure it still works if language is set to C++11:
+        options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11)
+        val = frame.EvaluateExpression('foo != nullptr', 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('foo != nullptr', options)
+        self.assertTrue(val.IsValid())
+        self.assertFalse(val.GetError().Success())
 
 if __name__ == '__main__':
     import atexit

Modified: lldb/trunk/test/expression_command/persistent_ptr_update/TestPersistentPtrUpdate.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/persistent_ptr_update/TestPersistentPtrUpdate.py?rev=246829&r1=246828&r2=246829&view=diff
==============================================================================
--- lldb/trunk/test/expression_command/persistent_ptr_update/TestPersistentPtrUpdate.py (original)
+++ lldb/trunk/test/expression_command/persistent_ptr_update/TestPersistentPtrUpdate.py Thu Sep  3 20:02:30 2015
@@ -42,7 +42,7 @@ class PersistentPtrUpdateTestCase(TestBa
 
         self.runCmd("run", RUN_SUCCEEDED)
         
-        self.runCmd("expr void* $foo = nullptr")
+        self.runCmd("expr void* $foo = 0")
         
         self.runCmd("continue")
         

Added: lldb/trunk/test/lang/mixed/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/mixed/Makefile?rev=246829&view=auto
==============================================================================
--- lldb/trunk/test/lang/mixed/Makefile (added)
+++ lldb/trunk/test/lang/mixed/Makefile Thu Sep  3 20:02:30 2015
@@ -0,0 +1,6 @@
+LEVEL = ../../make
+
+CXX_SOURCES := foo.cpp
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/lang/mixed/TestMixedLanguages.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/mixed/TestMixedLanguages.py?rev=246829&view=auto
==============================================================================
--- lldb/trunk/test/lang/mixed/TestMixedLanguages.py (added)
+++ lldb/trunk/test/lang/mixed/TestMixedLanguages.py Thu Sep  3 20:02:30 2015
@@ -0,0 +1,59 @@
+"""Test that lldb works correctly on compile units form different languages."""
+
+import os, time, re
+import unittest2
+import lldb
+from lldbtest import *
+
+class MixedLanguagesTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def test_language_of_frame(self):
+        """Test that the language defaults to the language of the current frame."""
+        self.buildDefault()
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Execute the cleanup function during test case tear down
+        # to restore the frame format.
+        def cleanup():
+            self.runCmd("settings set frame-format %s" % self.format_string, check=False)
+        self.addTearDownHook(cleanup)
+        self.runCmd("settings show frame-format")
+        m = re.match(
+                '^frame-format \(format-string\) = "(.*)\"$',
+                self.res.GetOutput())
+        self.assertTrue(m, "Bad settings string")
+        self.format_string = m.group(1)
+
+        # Change the default format to print the language.
+        format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, lang=${language}}\n"
+        self.runCmd("settings set frame-format %s" % format_string)
+        self.expect("settings show frame-format", SETTING_MSG("frame-format"),
+            substrs = [format_string])
+
+        # Run to BP at main (in main.c) and test that the language is C.
+        self.runCmd("breakpoint set -n main")
+        self.runCmd("run")
+        self.expect("thread backtrace",
+            substrs = ["`main", "lang=c"])
+        # Make sure evaluation of C++11 fails.
+        self.expect("expr foo != nullptr", error=True,
+            startstr = "error")
+
+        # Run to BP at foo (in foo.cpp) and test that the language is C++.
+        self.runCmd("breakpoint set -n foo")
+        self.runCmd("continue")
+        self.expect("thread backtrace",
+            substrs = ["`::foo()", "lang=c++"])
+        # Make sure we can evaluate an expression requiring C++11
+        # (note: C++11 is enabled by default for C++).
+        self.expect("expr foo != nullptr",
+            patterns = ["true"])
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/mixed/foo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/mixed/foo.cpp?rev=246829&view=auto
==============================================================================
--- lldb/trunk/test/lang/mixed/foo.cpp (added)
+++ lldb/trunk/test/lang/mixed/foo.cpp Thu Sep  3 20:02:30 2015
@@ -0,0 +1,11 @@
+namespace ns {
+    int func(void)
+    {
+        return 0;
+    }
+}
+
+extern "C" int foo(void)
+{
+    return ns::func();
+}

Added: lldb/trunk/test/lang/mixed/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/mixed/main.c?rev=246829&view=auto
==============================================================================
--- lldb/trunk/test/lang/mixed/main.c (added)
+++ lldb/trunk/test/lang/mixed/main.c Thu Sep  3 20:02:30 2015
@@ -0,0 +1,15 @@
+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();
+}




More information about the lldb-commits mailing list