This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Pretty printers for versioned namespace


On 10/01/2017 13:39, Jonathan Wakely wrote:
I've committed the attached patch, which passes the tests for the
default configuration and the versioned namespace configuration.

I added another helper function, strip_versioned_namespace, which is
more expressive than doing typename.replace(vers_nsp, '') everywhere.
I've also renamed vers_nsp to _versioned_namespace (using the naming
convention for global variables private to the module). I've added
checks so that if that variable is None then the extra printers and
special cases for the versioned namespace are skipped. That's not
currently used, but it would allow us to optimise things later if
needed.

Very nice feature indeed, see below.


I also needed to update the new SharedPtrMethodsMatcher to add
"(__\d+)?" to the regular expression.


@@ -1392,47 +1406,54 @@ def register_type_printers(obj):
    add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
    add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')

+    # Consider optional versioned namespace
+    opt_nsp = '(' + vers_nsp + ')?'
+
    # Do not show defaulted template arguments in class templates
    add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
+ '{0}unique_ptr<(.*), std::{0}default_delete<\\2 ?> >'.format(opt_nsp),
+        'unique_ptr<{2}>')

This is ugly. Mixing python string formatting with regular expressions
makes it harder to read, and is inconsistent with how the versioned
namespace is handled elsewhere. In Printer.add_version and
add_one_type_printer we just register two names, one using std:: and
one using std::__7::. We can do the same for the template type
printers.

Yes, your approach is much nicer even if it results in more type printer registered.

My plan was to submit the attached patch but this doesn't work as the python module seems to be loaded before libstdc++.so. If you know a way to test for versioned namespace before starting registering printers this patch might still be useful. Otherwise I will just forget it.

François
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 36dd81d..5e42988 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -79,6 +79,15 @@ try:
 except ImportError:
     pass
 
+_versioned_namespace = None
+
+# Use std::string to find out if versioned namespace has been activated.
+try:
+    gdb.lookup_type('std::string')
+except RuntimeError:
+    _versioned_namespace = '__7::'
+    pass
+
 # Starting with the type ORIG, search for the member type NAME.  This
 # handles searching upward through superclasses.  This is needed to
 # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
@@ -100,8 +109,6 @@ def find_type(orig, name):
             raise ValueError("Cannot find type %s::%s" % (str(orig), name))
         typ = field.type
 
-_versioned_namespace = '__7::'
-
 # Test if a type is a given template instantiation.
 def is_specialization_of(type, template_name):
     global _versioned_namespace
@@ -1222,11 +1229,12 @@ class Printer(object):
         self.subprinters.append(printer)
         self.lookup[name] = printer
 
-    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
+    # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION if needed.
     def add_version(self, base, name, function):
-        self.add(base + name, function)
         if _versioned_namespace:
             self.add(base + _versioned_namespace + name, function)
+        else:
+            self.add(base + name, function)
 
     # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
     def add_container(self, base, name, function):
@@ -1319,13 +1327,11 @@ class TemplateTypePrinter(object):
 
 def add_one_template_type_printer(obj, name, match, subst):
     match = '^std::' + match + '$'
-    printer = TemplateTypePrinter(name, match, 'std::' + subst)
-    gdb.types.register_type_printer(obj, printer)
     if _versioned_namespace:
-        # Add second type printer for same type in versioned namespace:
+        # Add type printer in versioned namespace:
         match = match.replace('std::', 'std::' + _versioned_namespace)
-        printer = TemplateTypePrinter(name, match, 'std::' + subst)
-        gdb.types.register_type_printer(obj, printer)
+    printer = TemplateTypePrinter(name, match, 'std::' + subst)
+    gdb.types.register_type_printer(obj, printer)
 
 class FilteringTypePrinter(object):
     def __init__(self, match, name):
@@ -1359,11 +1365,11 @@ class FilteringTypePrinter(object):
         return self._recognizer(self.match, self.name)
 
 def add_one_type_printer(obj, match, name):
-    printer = FilteringTypePrinter(match, 'std::' + name)
-    gdb.types.register_type_printer(obj, printer)
+    namespace = 'std::'
     if _versioned_namespace:
-        printer = FilteringTypePrinter(match, 'std::' + _versioned_namespace + name)
-        gdb.types.register_type_printer(obj, printer)
+        namespace += _versioned_namespace
+    printer = FilteringTypePrinter(match, namespace + name)
+    gdb.types.register_type_printer(obj, printer)
 
 def register_type_printers(obj):
     global _use_type_printing
@@ -1427,60 +1433,60 @@ def register_type_printers(obj):
 
     # Do not show defaulted template arguments in class templates
     add_one_template_type_printer(obj, 'unique_ptr<T>',
-            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
-            'unique_ptr<{1}>')
+        'unique_ptr<(.*), std::default_delete<\\1 ?> >',
+        'unique_ptr<{1}>')
 
     add_one_template_type_printer(obj, 'basic_string<T>',
-            'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
-            'basic_string<{1}>')
+        'basic_string<((un)?signed char), std::char_traits<\\1 ?>, std::allocator<\\1 ?> >',
+        'basic_string<{1}>')
 
     add_one_template_type_printer(obj, 'deque<T>',
-            'deque<(.*), std::allocator<\\1 ?> >',
-            'deque<{1}>')
+        'deque<(.*), std::allocator<\\1 ?> >',
+        'deque<{1}>')
     add_one_template_type_printer(obj, 'forward_list<T>',
-            'forward_list<(.*), std::allocator<\\1 ?> >',
-            'forward_list<{1}>')
+        'forward_list<(.*), std::allocator<\\1 ?> >',
+        'forward_list<{1}>')
     add_one_template_type_printer(obj, 'list<T>',
-            'list<(.*), std::allocator<\\1 ?> >',
-            'list<{1}>')
+        'list<(.*), std::allocator<\\1 ?> >',
+        'list<{1}>')
     add_one_template_type_printer(obj, 'vector<T>',
-            'vector<(.*), std::allocator<\\1 ?> >',
-            'vector<{1}>')
+        'vector<(.*), std::allocator<\\1 ?> >',
+        'vector<{1}>')
     add_one_template_type_printer(obj, 'map<Key, T>',
-            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'map<{1}, {2}>')
+        'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'map<{1}, {2}>')
     add_one_template_type_printer(obj, 'multimap<Key, T>',
-            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'multimap<{1}, {2}>')
+        'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'multimap<{1}, {2}>')
     add_one_template_type_printer(obj, 'set<T>',
-            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'set<{1}>')
+        'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        'set<{1}>')
     add_one_template_type_printer(obj, 'multiset<T>',
-            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
-            'multiset<{1}>')
+        'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+        'multiset<{1}>')
     add_one_template_type_printer(obj, 'unordered_map<Key, T>',
-            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_map<{1}, {2}>')
+        'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'unordered_map<{1}, {2}>')
     add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
-            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
-            'unordered_multimap<{1}, {2}>')
+        'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+        'unordered_multimap<{1}, {2}>')
     add_one_template_type_printer(obj, 'unordered_set<T>',
-            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_set<{1}>')
+        'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        'unordered_set<{1}>')
     add_one_template_type_printer(obj, 'unordered_multiset<T>',
-            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
-            'unordered_multiset<{1}>')
+        'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+        'unordered_multiset<{1}>')
 
     # strip the "fundamentals_v1" inline namespace from these types
     add_one_template_type_printer(obj, 'any<T>',
-            'experimental::fundamentals_v\d::any<(.*)>',
-            'experimental::any<\\1>')
+        'experimental::fundamentals_v\d::any<(.*)>',
+        'experimental::any<\\1>')
     add_one_template_type_printer(obj, 'optional<T>',
-            'experimental::fundamentals_v\d::optional<(.*)>',
-            'experimental::optional<\\1>')
+        'experimental::fundamentals_v\d::optional<(.*)>',
+        'experimental::optional<\\1>')
     add_one_template_type_printer(obj, 'basic_string_view<C>',
-            'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
-            'experimental::basic_string_view<\\1>')
+        'experimental::fundamentals_v\d::basic_string_view<(.*), std::char_traits<\\1> >',
+        'experimental::basic_string_view<\\1>')
 
 def register_libstdcxx_printers (obj):
     "Register libstdc++ pretty-printers with objfile Obj."



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]