[Lldb-commits] [lldb] r243099 - Improve C++ function name handling and step-in avoid regerxp handling

Tamas Berghammer tberghammer at google.com
Fri Jul 24 01:54:22 PDT 2015


Author: tberghammer
Date: Fri Jul 24 03:54:22 2015
New Revision: 243099

URL: http://llvm.org/viewvc/llvm-project?rev=243099&view=rev
Log:
Improve C++ function name handling and step-in avoid regerxp handling

If the function is a template then the return type is part of the
function name. This CL fixes the parsing of these function names in
the case when the return type contains ':'.

The name of free functions in C++ don't have context part. Fix the
logic geting the function name without arguments out from a full
function name to handle this case.

Change the handling of step-in-avoid-regexp to match the value against
the function name without it's arguments and return value. This is
required because the default regex ("^std::") would match any template
function returning an std object.

Fifferential revision: http://reviews.llvm.org/D11461

Modified:
    lldb/trunk/source/Core/Mangled.cpp
    lldb/trunk/source/Target/CPPLanguageRuntime.cpp
    lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
    lldb/trunk/test/functionalities/disassembly/TestDisassembleBreakpoint.py
    lldb/trunk/test/functionalities/inline-stepping/TestInlineStepping.py
    lldb/trunk/test/functionalities/inline-stepping/calling.cpp

Modified: lldb/trunk/source/Core/Mangled.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Mangled.cpp?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/source/Core/Mangled.cpp (original)
+++ lldb/trunk/source/Core/Mangled.cpp Fri Jul 24 03:54:22 2015
@@ -95,10 +95,11 @@ get_demangled_name_without_arguments (Co
             mangled_name_cstr[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
         {
             CPPLanguageRuntime::MethodName cxx_method (demangled);
-            if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty())
+            if (!cxx_method.GetBasename().empty())
             {
-                std::string shortname = cxx_method.GetContext().str();
-                shortname += "::";
+                std::string shortname;
+                if (!cxx_method.GetContext().empty())
+                    shortname = cxx_method.GetContext().str() + "::";
                 shortname += cxx_method.GetBasename().str();
                 ConstString result(shortname.c_str());
                 g_most_recent_mangled_to_name_sans_args.first = mangled;

Modified: lldb/trunk/source/Target/CPPLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CPPLanguageRuntime.cpp?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/source/Target/CPPLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/CPPLanguageRuntime.cpp Fri Jul 24 03:54:22 2015
@@ -306,17 +306,14 @@ CPPLanguageRuntime::MethodName::Parse()
                     llvm::StringRef lt_gt("<>", 2);
                     if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
                     {
+                        // Check for templated functions that include return type like: 'void foo<Int>()'
+                        context_start = full.rfind(' ', template_start);
+                        if (context_start == llvm::StringRef::npos)
+                            context_start = 0;
+
                         context_end = full.rfind(':', template_start);
-                        if (context_end == llvm::StringRef::npos)
-                        {
-                            // Check for templated functions that include return type like:
-                            // 'void foo<Int>()'
-                            context_end = full.rfind(' ', template_start);
-                            if (context_end != llvm::StringRef::npos)
-                            {
-                                context_start = context_end;
-                            }
-                        }
+                        if (context_end == llvm::StringRef::npos || context_end < context_start)
+                            context_end = context_start;
                     }
                     else
                     {

Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Fri Jul 24 03:54:22 2015
@@ -375,7 +375,7 @@ ThreadPlanStepInRange::FrameMatchesAvoid
         SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
         if (sc.symbol != NULL)
         {
-            const char *frame_function_name = sc.GetFunctionName().GetCString();
+            const char *frame_function_name = sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments).GetCString();
             if (frame_function_name)
             {
                 size_t num_matches = 0;

Modified: lldb/trunk/test/functionalities/disassembly/TestDisassembleBreakpoint.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/disassembly/TestDisassembleBreakpoint.py?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/disassembly/TestDisassembleBreakpoint.py (original)
+++ lldb/trunk/test/functionalities/disassembly/TestDisassembleBreakpoint.py Fri Jul 24 03:54:22 2015
@@ -53,7 +53,7 @@ class DisassemblyTestCase(TestBase):
             self.assertFalse(op in disassembly)
 
         # make sure a few reasonable assembly instructions are here
-        self.expect(disassembly, exe=False, startstr = "a.out`sum(int, int)", substrs = instructions)
+        self.expect(disassembly, exe=False, startstr = "a.out`sum", substrs = instructions)
 
 if __name__ == '__main__':
     import atexit

Modified: lldb/trunk/test/functionalities/inline-stepping/TestInlineStepping.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/inline-stepping/TestInlineStepping.py?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/inline-stepping/TestInlineStepping.py (original)
+++ lldb/trunk/test/functionalities/inline-stepping/TestInlineStepping.py Fri Jul 24 03:54:22 2015
@@ -45,6 +45,21 @@ class TestInlineStepping(TestBase):
         """Test stepping over and into inlined functions."""
         self.buildDwarf()
         self.inline_stepping_step_over()
+    
+    @skipUnlessDarwin
+    @python_api_test
+    @dsym_test
+    def test_step_in_template_with_dsym_and_python_api(self):
+        """Test stepping in to templated functions."""
+        self.buildDsym()
+        self.step_in_template()
+
+    @python_api_test
+    @dwarf_test
+    def test_step_in_template_with_dwarf_and_python_api(self):
+        """Test stepping in to templated functions."""
+        self.buildDwarf()
+        self.step_in_template()
 
     def setUp(self):
         # Call super's setUp().
@@ -120,7 +135,6 @@ class TestInlineStepping(TestBase):
             target_line_entry.SetLine(step_stop_line)
             self.do_step (step_pattern[1], target_line_entry, test_stack_depth)
         
-
     def inline_stepping(self):
         """Use Python APIs to test stepping over and hitting breakpoints."""
         exe = os.path.join(os.getcwd(), "a.out")
@@ -245,8 +259,40 @@ class TestInlineStepping(TestBase):
                          ["// At increment in caller_ref_2.", "over"]]
         self.run_step_sequence (step_sequence)
 
+    def step_in_template(self):
+        """Use Python APIs to test stepping in to templated functions."""
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        break_1_in_main = target.BreakpointCreateBySourceRegex ('// Call max_value template', self.main_source_spec)
+        self.assertTrue(break_1_in_main, VALID_BREAKPOINT)
         
+        break_2_in_main = target.BreakpointCreateBySourceRegex ('// Call max_value specialized', self.main_source_spec)
+        self.assertTrue(break_2_in_main, VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        self.process = target.LaunchSimple (None, None, self.get_process_working_directory())
+        self.assertTrue(self.process, PROCESS_IS_VALID)
+
+        # The stop reason of the thread should be breakpoint.
+        threads = lldbutil.get_threads_stopped_at_breakpoint (self.process, break_1_in_main)
+
+        if len(threads) != 1:
+            self.fail ("Failed to stop at first breakpoint in main.")
+
+        self.thread = threads[0]
+
+        step_sequence = [["// In max_value template", "into"]]
+        self.run_step_sequence(step_sequence)
+        
+        threads = lldbutil.continue_to_breakpoint (self.process, break_2_in_main)
+        self.assertEqual(len(threads), 1, "Successfully ran to call site of second caller_trivial_1 call.")
+        self.thread = threads[0]
         
+        step_sequence = [["// In max_value specialized", "into"]]
+        self.run_step_sequence(step_sequence)
 
 if __name__ == '__main__':
     import atexit

Modified: lldb/trunk/test/functionalities/inline-stepping/calling.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/inline-stepping/calling.cpp?rev=243099&r1=243098&r2=243099&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/inline-stepping/calling.cpp (original)
+++ lldb/trunk/test/functionalities/inline-stepping/calling.cpp Fri Jul 24 03:54:22 2015
@@ -1,4 +1,6 @@
-#include <stdio.h>
+#include <algorithm>
+#include <cstdio>
+#include <string>
 
 inline int inline_ref_1 (int &value) __attribute__((always_inline));
 inline int inline_ref_2 (int &value) __attribute__((always_inline));
@@ -97,6 +99,18 @@ inline_trivial_2 ()
     called_by_inline_trivial (); // At caller_by_inline_trivial in inline_trivial_2.
 }
 
+template<typename T> T
+max_value(const T& lhs, const T& rhs)
+{
+    return std::max(lhs, rhs); // In max_value template
+}
+
+template<> std::string
+max_value(const std::string& lhs, const std::string& rhs)
+{
+    return (lhs.size() > rhs.size()) ? lhs : rhs; // In max_value specialized
+}
+
 int
 main (int argc, char **argv)
 {
@@ -114,6 +128,9 @@ main (int argc, char **argv)
     caller_ref_1 (argc); // At second call of caller_ref_1 in main. 
     
     function_to_call (); // Make sure debug info for this function gets generated.
+    
+    max_value(123, 456);                                // Call max_value template
+    max_value(std::string("abc"), std::string("0022")); // Call max_value specialized
 
     return 0;            // About to return from main.
 }





More information about the lldb-commits mailing list