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]

debug mode maintenance patch


Hi

    This is a patch to clean the debug mode code.

I have introduced a new debug header, assertions.h, so that headers that only need _GLIBCXX_DEBUG_ASSERT do not have to include the big debug.h. I also introduce functions.tcc to isolate implementation of __foreign_iterator which require a number of other headers.

I reorganized _Error_formatter. Nested _Parameter is now public like several format methods so that I am able to move some code to debug.cc. I would have needed to export new symbols otherwise. I introduced 2 new type of debug parameters, __instance for any functor, __iterator_value_type to report iterator value_type. I will use those in new debug checks to come.

Note that I try to regenerate include/Makefile.in with autoreconf 2.64 but it was producing a lot of modifications in all Makefile.in. Can someone check if those files are up to date ?

2015-02-19  FranÃois Dumont  <fdumont@gcc.gnu.org>

    * include/debug/debug.h ([_GLIBCXX_DEBUG_ASSERT,
    _GLIBCXX_DEBUG_PEDASSERT, _GLIBCXX_DEBUG_ONLY]): Move definition...
    * include/debug/assertions.h: ...here, new.
    * include/debug/formatter.h
    (struct _Error_formatter::_Is_iterator_value_type): New.
    (struct _Error_formatter::_Is_instance): New.
    (struct _Error_formatter::_Parameter): Make public and not friend
    anymore.
    (_Error_formatter::_Parameter::__instance): New _M_kind enum entry.
    (_Error_formatter::_Parameter::__iterator_value_type): New _M_kind enum
    entry.
    (struct _Error_formatter::_Parameter::_Type): New.
    (struct _Error_formatter::_Parameter::_Instance): New, inherit from
    latter.
    (union _Error_formatter::_Parameter::_M_variant): Reorganize.
    (_Parameter(_Iterator const&, const char*, _Is_iterator)): Make all
    overloads take iterator through a const reference.
    (_Parameter(const _Iterator&, const char*, _Is_iterator_value_type)):
    New.
    (_Parameter(const _Type&, const char*, _Is_instance)): New.
    (_Error_formatter::_M_print_type): Delete.
    (_Error_formatter::_M_iterator_value_type): New.
    (_Error_formatter::_M_instance): New.
    * include/debug/functions.h (__foreign_iterator): Move definition...
    * include/debug/functions.tcc: ...here, new.
    * include/Makefile.am: Add new above debug files.
    * include/Makefile.in: Regenerate.
    * include/debug/safe_iterator.h: Replace debug.h include with
    assertions.h.
    (__check_dereferenceable, __valid_range): Move here overload for
    _Safe_iterator.
    (struct __is_safe_random_iterator): Move here partial specialization
    for _Safe_iterator.
    (__check_singular_aux): Move...
    * include/debug/safe_base.h (__check_singular_aux): ... here.
    * include/debug/safe_local_iterator.h (__check_dereferenceable)
    (__valid_range): Move here overload for _Safe_local_iterator.
    * include/debug/safe_sequence.h: Replace debug.h with assertions.h.
    Remove _Safe_iterator declaration.
    * include/debug/safe_unordered_container.h: Replace debug.h with
    assertions.h.
    * include/debug/array: Replace safe_sequence.h include with
    formatter.h and macros.h.
    * include/debug/deque: Include functions.tcc.
    * include/debug/forward_list: Likewise.
    * include/debug/list: Likewise.
    * include/debug/string: Likewise.
    * include/debug/vector: Likewise.
    * include/bits/unique_ptr.h: Replace debug.h include with new
    assertions.h.
    * include/bits/stl_iterator_base_funcs.h: Likewise.
    * testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
    Adjust dg-error line number.
    * testsuite/23_containers/array/tuple_interface/
    tuple_element_debug_neg.cc: Likewise.
    * src/c++11/debug.cc: Adapt.

Tested under Linux x86_64 debug mode.

Will commit in a couple of days if no complain.

FranÃois

Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 223630)
+++ include/Makefile.am	(working copy)
@@ -759,6 +759,7 @@
 debug_builddir = ./debug
 debug_headers = \
 	${debug_srcdir}/array \
+	${debug_srcdir}/assertions.h \
 	${debug_srcdir}/bitset \
 	${debug_srcdir}/debug.h \
 	${debug_srcdir}/deque \
@@ -765,6 +766,7 @@
 	${debug_srcdir}/formatter.h \
 	${debug_srcdir}/forward_list \
 	${debug_srcdir}/functions.h \
+	${debug_srcdir}/functions.tcc \
 	${debug_srcdir}/list \
 	${debug_srcdir}/map \
 	${debug_srcdir}/macros.h \
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 223630)
+++ include/Makefile.in	(working copy)
@@ -1040,6 +1040,7 @@
 debug_builddir = ./debug
 debug_headers = \
 	${debug_srcdir}/array \
+	${debug_srcdir}/assertions.h \
 	${debug_srcdir}/bitset \
 	${debug_srcdir}/debug.h \
 	${debug_srcdir}/deque \
@@ -1046,6 +1047,7 @@
 	${debug_srcdir}/formatter.h \
 	${debug_srcdir}/forward_list \
 	${debug_srcdir}/functions.h \
+	${debug_srcdir}/functions.tcc \
 	${debug_srcdir}/list \
 	${debug_srcdir}/map \
 	${debug_srcdir}/macros.h \
Index: include/bits/stl_iterator_base_funcs.h
===================================================================
--- include/bits/stl_iterator_base_funcs.h	(revision 223630)
+++ include/bits/stl_iterator_base_funcs.h	(working copy)
@@ -62,7 +62,7 @@
 #pragma GCC system_header
 
 #include <bits/concept_check.h>
-#include <debug/debug.h>
+#include <debug/assertions.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
Index: include/bits/unique_ptr.h
===================================================================
--- include/bits/unique_ptr.h	(revision 223630)
+++ include/bits/unique_ptr.h	(working copy)
@@ -31,7 +31,7 @@
 #define _UNIQUE_PTR_H 1
 
 #include <bits/c++config.h>
-#include <debug/debug.h>
+#include <debug/assertions.h>
 #include <type_traits>
 #include <utility>
 #include <tuple>
Index: include/debug/array
===================================================================
--- include/debug/array	(revision 223630)
+++ include/debug/array	(working copy)
@@ -31,7 +31,8 @@
 
 #pragma GCC system_header
 
-#include <debug/safe_sequence.h>
+#include <debug/formatter.h>
+#include <debug/macros.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
Index: include/debug/assertions.h
===================================================================
--- include/debug/assertions.h	(revision 0)
+++ include/debug/assertions.h	(working copy)
@@ -0,0 +1,52 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/assertions.h
+ *  This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H
+#define _GLIBCXX_DEBUG_ASSERTIONS_H 1
+
+#ifndef _GLIBCXX_DEBUG
+
+# define _GLIBCXX_DEBUG_ASSERT(_Condition)
+# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
+# define _GLIBCXX_DEBUG_ONLY(_Statement) ;
+
+#else
+
+#define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition)
+
+#ifdef _GLIBCXX_DEBUG_PEDANTIC
+# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition)
+#else
+# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
+#endif
+
+# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement
+
+#endif
+
+#endif // _GLIBCXX_DEBUG_ASSERTIONS
Index: include/debug/debug.h
===================================================================
--- include/debug/debug.h	(revision 223630)
+++ include/debug/debug.h	(working copy)
@@ -37,6 +37,8 @@
  *  the standard library algorithms.
 */
 
+#include <debug/assertions.h>
+
 // Debug mode namespaces.
 
 /**
@@ -58,9 +60,6 @@
 
 #ifndef _GLIBCXX_DEBUG
 
-# define _GLIBCXX_DEBUG_ASSERT(_Condition)
-# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
-# define _GLIBCXX_DEBUG_ONLY(_Statement) ;
 # define __glibcxx_requires_cond(_Cond,_Msg)
 # define __glibcxx_requires_valid_range(_First,_Last)
 # define __glibcxx_requires_non_empty_range(_First,_Last)
@@ -83,16 +82,6 @@
 
 # include <debug/macros.h>
 
-#define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition)
-
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
-# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition)
-#else
-# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
-#endif
-
-# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement
-
 # define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg)
 # define __glibcxx_requires_valid_range(_First,_Last) \
      __glibcxx_check_valid_range(_First,_Last)
Index: include/debug/deque
===================================================================
--- include/debug/deque	(revision 223630)
+++ include/debug/deque	(working copy)
@@ -636,4 +636,6 @@
 } // namespace __debug
 } // namespace std
 
+#include <debug/functions.tcc>
+
 #endif
Index: include/debug/formatter.h
===================================================================
--- include/debug/formatter.h	(revision 223630)
+++ include/debug/formatter.h	(working copy)
@@ -154,8 +154,11 @@
 
     // Tags denoting the type of parameter for construction
     struct _Is_iterator { };
+    struct _Is_iterator_value_type { };
     struct _Is_sequence { };
+    struct _Is_instance { };
 
+  public:
     // A parameter that may be referenced by an error message
     struct _Parameter
     {
@@ -165,17 +168,27 @@
 	__iterator,
 	__sequence,
 	__integer,
-	__string
+	__string,
+	__instance,
+	__iterator_value_type
       } _M_kind;
 
+      struct _Type
+      {
+	const char*		_M_name;
+	const type_info*	_M_type;
+      };
+
+      struct _Instance : _Type
+      {
+	const void*		_M_address;
+      };
+
       union
       {
 	// When _M_kind == __iterator
-	struct
+	struct : _Instance
 	{
-	  const char*		_M_name;
-	  const void*		_M_address;
-	  const type_info*	_M_type;
 	  _Constness		_M_constness;
 	  _Iterator_state	_M_state;
 	  const void*		_M_sequence;
@@ -183,12 +196,7 @@
 	} _M_iterator;
 
 	// When _M_kind == __sequence
-	struct
-	{
-	  const char*		_M_name;
-	  const void*		_M_address;
-	  const type_info*	_M_type;
-	} _M_sequence;
+	_Instance _M_sequence;
 
 	// When _M_kind == __integer
 	struct
@@ -203,6 +211,12 @@
 	  const char*		_M_name;
 	  const char*		_M_value;
 	} _M_string;
+
+	// When _M_kind == __instance
+	_Instance _M_instance;
+
+	// When _M_kind == __iterator_value_type
+	_Type _M_iterator_value_type;
       } _M_variant;
 
       _Parameter() : _M_kind(__unused_param), _M_variant() { }
@@ -222,7 +236,7 @@
       }
 
       template<typename _Iterator, typename _Sequence>
-	_Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it,
+	_Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it,
 		   const char* __name, _Is_iterator)
 	: _M_kind(__iterator),  _M_variant()
 	{
@@ -252,7 +266,7 @@
 	}
 
       template<typename _Iterator, typename _Sequence>
-	_Parameter(const _Safe_local_iterator<_Iterator, _Sequence>& __it,
+	_Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
 		   const char* __name, _Is_iterator)
 	: _M_kind(__iterator),  _M_variant()
 	{
@@ -280,33 +294,33 @@
 	}
 
       template<typename _Type>
-	_Parameter(const _Type*& __it, const char* __name, _Is_iterator)
+	_Parameter(const _Type* const& __it, const char* __name, _Is_iterator)
 	: _M_kind(__iterator), _M_variant()
 	{
 	  _M_variant._M_iterator._M_name = __name;
 	  _M_variant._M_iterator._M_address = &__it;
 	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
-	  _M_variant._M_iterator._M_constness = __mutable_iterator;
-	  _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
+	  _M_variant._M_iterator._M_constness = __const_iterator;
+	  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
 	  _M_variant._M_iterator._M_sequence = 0;
 	  _M_variant._M_iterator._M_seq_type = 0;
 	}
 
       template<typename _Type>
-	_Parameter(_Type*& __it, const char* __name, _Is_iterator)
+	_Parameter(_Type* const& __it, const char* __name, _Is_iterator)
 	: _M_kind(__iterator), _M_variant()
 	{
 	  _M_variant._M_iterator._M_name = __name;
 	  _M_variant._M_iterator._M_address = &__it;
 	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
-	  _M_variant._M_iterator._M_constness = __const_iterator;
-	  _M_variant._M_iterator._M_state = __it? __unknown_state : __singular;
+	  _M_variant._M_iterator._M_constness = __mutable_iterator;
+	  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
 	  _M_variant._M_iterator._M_sequence = 0;
 	  _M_variant._M_iterator._M_seq_type = 0;
 	}
 
       template<typename _Iterator>
-	_Parameter(const _Iterator& __it, const char* __name, _Is_iterator)
+	_Parameter(_Iterator const& __it, const char* __name, _Is_iterator)
 	: _M_kind(__iterator), _M_variant()
 	{
 	  _M_variant._M_iterator._M_name = __name;
@@ -314,7 +328,7 @@
 	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
 	  _M_variant._M_iterator._M_constness = __unknown_constness;
 	  _M_variant._M_iterator._M_state =
-	    __gnu_debug::__check_singular(__it)? __singular : __unknown_state;
+	    __gnu_debug::__check_singular(__it) ? __singular : __unknown_state;
 	  _M_variant._M_iterator._M_sequence = 0;
 	  _M_variant._M_iterator._M_seq_type = 0;
 	}
@@ -339,6 +353,25 @@
 	  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
 	}
 
+      template<typename _Iterator>
+	_Parameter(const _Iterator& __it, const char* __name,
+		   _Is_iterator_value_type)
+	: _M_kind(__iterator_value_type), _M_variant()
+	{
+	  _M_variant._M_iterator_value_type._M_name = __name;
+	  _M_variant._M_iterator_value_type._M_type =
+	    _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type);
+	}
+
+      template<typename _Type>
+	_Parameter(const _Type& __inst, const char* __name, _Is_instance)
+	: _M_kind(__instance), _M_variant()
+	{
+	  _M_variant._M_instance._M_name = __name;
+	  _M_variant._M_instance._M_address = &__inst;
+	  _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type);
+	}
+
       void
       _M_print_field(const _Error_formatter* __formatter,
 		     const char* __name) const;
@@ -347,9 +380,6 @@
       _M_print_description(const _Error_formatter* __formatter) const;
     };
 
-    friend struct _Parameter;
-
-  public:
     template<typename _Iterator>
       const _Error_formatter&
       _M_iterator(const _Iterator& __it, const char* __name = 0)  const
@@ -360,6 +390,17 @@
 	return *this;
       }
 
+    template<typename _Iterator>
+      const _Error_formatter&
+      _M_iterator_value_type(const _Iterator& __it,
+			     const char* __name = 0)  const
+      {
+	if (_M_num_parameters < std::size_t(__max_parameters))
+	  _M_parameters[_M_num_parameters++] =
+	    _Parameter(__it, __name, _Is_iterator_value_type());
+	return *this;
+      }
+
     const _Error_formatter&
     _M_integer(long __value, const char* __name = 0) const
     {
@@ -386,6 +427,16 @@
 	return *this;
       }
 
+    template<typename _Type>
+      const _Error_formatter&
+      _M_instance(const _Type& __inst, const char* __name = 0) const
+      {
+	if (_M_num_parameters < std::size_t(__max_parameters))
+	  _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
+							  _Is_instance());
+	return *this;
+      }
+
     const _Error_formatter&
     _M_message(const char* __text) const
     { _M_text = __text; return *this; }
@@ -396,12 +447,6 @@
     _GLIBCXX_NORETURN void
     _M_error() const;
 
-  private:
-    _Error_formatter(const char* __file, std::size_t __line)
-    : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0),
-      _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
-    { _M_get_max_length(); }
-
     template<typename _Tp>
       void
       _M_format_word(char*, int, const char*, _Tp) const throw ();
@@ -412,9 +457,11 @@
     void
     _M_print_string(const char* __string) const;
 
-    void
-    _M_print_type(const type_info* __info,
-		  const char* __unknown_name) const;
+  private:
+    _Error_formatter(const char* __file, std::size_t __line)
+    : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0),
+      _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
+    { _M_get_max_length(); }
 
     void
     _M_get_max_length() const throw ();
Index: include/debug/forward_list
===================================================================
--- include/debug/forward_list	(revision 223630)
+++ include/debug/forward_list	(working copy)
@@ -824,4 +824,6 @@
 #endif
 }
 
+#include <debug/functions.tcc>
+
 #endif
Index: include/debug/functions.h
===================================================================
--- include/debug/functions.h	(revision 223630)
+++ include/debug/functions.h	(working copy)
@@ -33,11 +33,7 @@
 #include <bits/stl_iterator_base_types.h> // for iterator_traits, categories and
 					  // _Iter_base
 #include <bits/cpp_type_traits.h>	  // for __is_integer
-#include <bits/move.h>                    // for __addressof and addressof
-#include <bits/stl_function.h>		  // for less
-#if __cplusplus >= 201103L
-# include <type_traits>			  // for is_lvalue_reference and __and_
-#endif
+
 #include <debug/formatter.h>
 
 namespace __gnu_debug
@@ -45,9 +41,6 @@
   template<typename _Iterator, typename _Sequence>
     class _Safe_iterator;
 
-  template<typename _Iterator, typename _Sequence>
-    class _Safe_local_iterator;
-
   template<typename _Sequence>
     struct _Insert_range_from_self_is_safe
     { enum { __value = 0 }; };
@@ -85,19 +78,6 @@
     __check_dereferenceable(const _Tp* __ptr)
     { return __ptr; }
 
-  /** Safe iterators know if they are dereferenceable. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
-    { return __x._M_dereferenceable(); }
-
-  /** Safe local iterators know if they are dereferenceable. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __check_dereferenceable(const _Safe_local_iterator<_Iterator,
-						       _Sequence>& __x)
-    { return __x._M_dereferenceable(); }
-
   /** If the distance between two random access iterators is
    *  nonnegative, assume the range is valid.
   */
@@ -150,20 +130,6 @@
       return __valid_range_aux(__first, __last, _Integral());
     }
 
-  /** Safe iterators know how to check if they form a valid range. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
-		  const _Safe_iterator<_Iterator, _Sequence>& __last)
-    { return __first._M_valid_range(__last); }
-
-  /** Safe local iterators know how to check if they form a valid range. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
-		  const _Safe_local_iterator<_Iterator, _Sequence>& __last)
-    { return __first._M_valid_range(__last); }
-
   /* Checks that [first, last) is a valid range, and then returns
    * __first. This routine is useful when we can't use a separate
    * assertion statement because, e.g., we are in a constructor.
@@ -178,121 +144,11 @@
       return __first;
     }
 
-  /* Handle the case where __other is a pointer to _Sequence::value_type. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
-			    const typename _Sequence::value_type* __other)
-    {
-      typedef const typename _Sequence::value_type* _PointerType;
-      typedef std::less<_PointerType> _Less;
-#if __cplusplus >= 201103L
-      constexpr _Less __l{};
-#else
-      const _Less __l = _Less();
-#endif
-      const _Sequence* __seq = __it._M_get_sequence();
-      const _PointerType __begin = std::__addressof(*__seq->_M_base().begin());
-      const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1));
-
-      // Check whether __other points within the contiguous storage.
-      return __l(__other, __begin) || __l(__end, __other);
-    }
-
-  /* Fallback overload for when we can't tell, assume it is valid. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...)
-    { return true; }
-
-  /* Handle sequences with contiguous storage */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
-    inline bool
-    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
-			    const _InputIterator& __other,
-			    const _InputIterator& __other_end,
-			    std::__true_type)
-    {
-      if (__other == __other_end)
-	return true;  // inserting nothing is safe even if not foreign iters
-      if (__it._M_get_sequence()->begin() == __it._M_get_sequence()->end())
-	return true;  // can't be self-inserting if self is empty
-      return __foreign_iterator_aux4(__it, std::__addressof(*__other));
-    }
-
-  /* Handle non-contiguous containers, assume it is valid. */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
-    inline bool
-    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&,
-			    const _InputIterator&, const _InputIterator&,
-			    std::__false_type)
-    { return true; }
-
-  /** Handle debug iterators from the same type of container. */
-  template<typename _Iterator, typename _Sequence, typename _OtherIterator>
-    inline bool
-    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
-		const _Safe_iterator<_OtherIterator, _Sequence>& __other,
-		const _Safe_iterator<_OtherIterator, _Sequence>&)
-    { return __it._M_get_sequence() != __other._M_get_sequence(); }
-
-  /** Handle debug iterators from different types of container. */
-  template<typename _Iterator, typename _Sequence, typename _OtherIterator,
-	   typename _OtherSequence>
-    inline bool
-    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
-		const _Safe_iterator<_OtherIterator, _OtherSequence>&,
-		const _Safe_iterator<_OtherIterator, _OtherSequence>&)
-    { return true; }
-
-  /* Handle non-debug iterators. */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
-    inline bool
-    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
-			    const _InputIterator& __other,
-			    const _InputIterator& __other_end)
-    {
-#if __cplusplus < 201103L
-      typedef _Is_contiguous_sequence<_Sequence> __tag;
-#else
-      using __lvalref = std::is_lvalue_reference<
-	typename std::iterator_traits<_InputIterator>::reference>;
-      using __contiguous = _Is_contiguous_sequence<_Sequence>;
-      using __tag = typename std::conditional<__lvalref::value, __contiguous,
-					      std::__false_type>::type;
-#endif
-      return __foreign_iterator_aux3(__it, __other, __other_end, __tag());
-    }
-
-  /* Handle the case where we aren't really inserting a range after all */
-  template<typename _Iterator, typename _Sequence, typename _Integral>
-    inline bool
-    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&,
-			   _Integral, _Integral,
-			   std::__true_type)
-    { return true; }
-
-  /* Handle all iterators. */
   template<typename _Iterator, typename _Sequence,
 	   typename _InputIterator>
-    inline bool
-    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
-			   _InputIterator __other, _InputIterator __other_end,
-			   std::__false_type)
-    {
-      return _Insert_range_from_self_is_safe<_Sequence>::__value
-	     || __foreign_iterator_aux2(__it, __other, __other_end);
-    }
-
-  template<typename _Iterator, typename _Sequence,
-	   typename _InputIterator>
-    inline bool
+    bool
     __foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
-		       _InputIterator __other, _InputIterator __other_end)
-    {
-      typedef typename std::__is_integer<_InputIterator>::__type _Integral;
-      return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
-    }
+		       _InputIterator __other, _InputIterator __other_end);
 
   /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
   template<typename _CharT, typename _Integer>
@@ -535,13 +391,6 @@
       typedef std::__false_type __type;
     };
 
-  template<typename _Iterator, typename _Sequence>
-    struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
-    : std::__are_same<std::random_access_iterator_tag,
-                      typename std::iterator_traits<_Iterator>::
-		      iterator_category>
-    { };
-
   template<typename _Iterator>
     struct _Siter_base
     : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
Index: include/debug/functions.tcc
===================================================================
--- include/debug/functions.tcc	(revision 0)
+++ include/debug/functions.tcc	(working copy)
@@ -0,0 +1,159 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/functions.tcc
+ *  This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_FUNCTIONS_TCC
+#define _GLIBCXX_DEBUG_FUNCTIONS_TCC 1
+
+#include <bits/move.h>			// for __addressof and addressof
+#include <bits/stl_function.h>		// for less
+#if __cplusplus >= 201103L
+# include <type_traits>			// for is_lvalue_reference
+					// conditional.
+#endif
+
+namespace __gnu_debug
+{
+  /* Handle the case where __other is a pointer to _Sequence::value_type. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
+			    const typename _Sequence::value_type* __other)
+    {
+      typedef const typename _Sequence::value_type* _PointerType;
+      typedef std::less<_PointerType> _Less;
+#if __cplusplus >= 201103L
+      constexpr _Less __l{};
+#else
+      const _Less __l = _Less();
+#endif
+      const _Sequence* __seq = __it._M_get_sequence();
+      const _PointerType __begin = std::__addressof(*__seq->_M_base().begin());
+      const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1));
+
+      // Check whether __other points within the contiguous storage.
+      return __l(__other, __begin) || __l(__end, __other);
+    }
+
+  /* Fallback overload for when we can't tell, assume it is valid. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...)
+    { return true; }
+
+  /* Handle sequences with contiguous storage */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
+			    const _InputIterator& __other,
+			    const _InputIterator& __other_end,
+			    std::__true_type)
+    {
+      if (__other == __other_end)
+	return true;  // inserting nothing is safe even if not foreign iters
+      if (__it._M_get_sequence()->begin() == __it._M_get_sequence()->end())
+	return true;  // can't be self-inserting if self is empty
+      return __foreign_iterator_aux4(__it, std::__addressof(*__other));
+    }
+
+  /* Handle non-contiguous containers, assume it is valid. */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&,
+			    const _InputIterator&, const _InputIterator&,
+			    std::__false_type)
+    { return true; }
+
+  /** Handle debug iterators from the same type of container. */
+  template<typename _Iterator, typename _Sequence, typename _OtherIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+		const _Safe_iterator<_OtherIterator, _Sequence>& __other,
+		const _Safe_iterator<_OtherIterator, _Sequence>&)
+    { return __it._M_get_sequence() != __other._M_get_sequence(); }
+
+  /** Handle debug iterators from different types of container. */
+  template<typename _Iterator, typename _Sequence, typename _OtherIterator,
+	   typename _OtherSequence>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+		const _Safe_iterator<_OtherIterator, _OtherSequence>&,
+		const _Safe_iterator<_OtherIterator, _OtherSequence>&)
+    { return true; }
+
+  /* Handle non-debug iterators. */
+  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+			    const _InputIterator& __other,
+			    const _InputIterator& __other_end)
+    {
+#if __cplusplus < 201103L
+      typedef _Is_contiguous_sequence<_Sequence> __tag;
+#else
+      using __lvalref = std::is_lvalue_reference<
+	typename std::iterator_traits<_InputIterator>::reference>;
+      using __contiguous = _Is_contiguous_sequence<_Sequence>;
+      using __tag = typename std::conditional<__lvalref::value, __contiguous,
+					      std::__false_type>::type;
+#endif
+      return __foreign_iterator_aux3(__it, __other, __other_end, __tag());
+    }
+
+  /* Handle the case where we aren't really inserting a range after all */
+  template<typename _Iterator, typename _Sequence, typename _Integral>
+    inline bool
+    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&,
+			   _Integral, _Integral,
+			   std::__true_type)
+    { return true; }
+
+  /* Handle all iterators. */
+  template<typename _Iterator, typename _Sequence,
+	   typename _InputIterator>
+    inline bool
+    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
+			   _InputIterator __other, _InputIterator __other_end,
+			   std::__false_type)
+    {
+      return _Insert_range_from_self_is_safe<_Sequence>::__value
+	     || __foreign_iterator_aux2(__it, __other, __other_end);
+    }
+
+  template<typename _Iterator, typename _Sequence,
+	   typename _InputIterator>
+    inline bool
+    __foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
+		       _InputIterator __other, _InputIterator __other_end)
+    {
+      typedef typename std::__is_integer<_InputIterator>::__type _Integral;
+      return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
+    }
+
+} // namespace __gnu_debug
+
+#endif
Index: include/debug/list
===================================================================
--- include/debug/list	(revision 223630)
+++ include/debug/list	(working copy)
@@ -797,4 +797,6 @@
 }
 #endif
 
+#include <debug/functions.tcc>
+
 #endif
Index: include/debug/safe_base.h
===================================================================
--- include/debug/safe_base.h	(revision 223630)
+++ include/debug/safe_base.h	(working copy)
@@ -159,6 +159,13 @@
     }
   };
 
+  /** Iterators that derive from _Safe_iterator_base can be determined singular
+   *  or non-singular.
+   **/
+  inline bool
+  __check_singular_aux(const _Safe_iterator_base* __x)
+  { return __x->_M_singular(); }
+
   /**
    * @brief Base class that supports tracking of iterators that
    * reference a sequence.
Index: include/debug/safe_iterator.h
===================================================================
--- include/debug/safe_iterator.h	(revision 223630)
+++ include/debug/safe_iterator.h	(working copy)
@@ -29,7 +29,7 @@
 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
 
-#include <debug/debug.h>
+#include <debug/assertions.h>
 #include <debug/macros.h>
 #include <debug/functions.h>
 #include <debug/safe_base.h>
@@ -55,13 +55,6 @@
 	{ return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
     };
 
-  /** Iterators that derive from _Safe_iterator_base can be determined singular
-   *  or non-singular.
-   **/
-  inline bool
-  __check_singular_aux(const _Safe_iterator_base* __x)
-  { return __x->_M_singular(); }
-
   /** The precision to which we can calculate the distance between
    *  two iterators.
    */
@@ -93,11 +86,7 @@
     inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
 		     _Distance_precision>
     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
-    {
-      typedef typename std::iterator_traits<_Iterator>::iterator_category
-	  _Category;
-      return __get_distance(__lhs, __rhs, _Category());
-    }
+    { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
 
   /** \brief Safe iterator wrapper.
    *
@@ -768,6 +757,27 @@
     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
 	      const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
     { return __i + __n; }
+
+  /** Safe iterators know if they are dereferenceable. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
+    { return __x._M_dereferenceable(); }
+
+  /** Safe iterators know how to check if they form a valid range. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
+		  const _Safe_iterator<_Iterator, _Sequence>& __last)
+    { return __first._M_valid_range(__last); }
+
+  template<typename _Iterator, typename _Sequence>
+    struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
+    : std::__are_same<std::random_access_iterator_tag,
+                      typename std::iterator_traits<_Iterator>::
+		      iterator_category>
+    { };
+
 } // namespace __gnu_debug
 
 #include <debug/safe_iterator.tcc>
Index: include/debug/safe_local_iterator.h
===================================================================
--- include/debug/safe_local_iterator.h	(revision 223630)
+++ include/debug/safe_local_iterator.h	(working copy)
@@ -29,11 +29,7 @@
 #ifndef _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H
 #define _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H 1
 
-#include <debug/debug.h>
-#include <debug/macros.h>
-#include <debug/functions.h>
 #include <debug/safe_unordered_base.h>
-#include <ext/type_traits.h>
 
 namespace __gnu_debug
 {
@@ -432,6 +428,20 @@
 			    ._M_iterator(__rhs, "rhs"));
       return __lhs.base() != __rhs.base();
     }
+
+  /** Safe local iterators know if they are dereferenceable. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __check_dereferenceable(const _Safe_local_iterator<_Iterator,
+						       _Sequence>& __x)
+    { return __x._M_dereferenceable(); }
+
+  /** Safe local iterators know how to check if they form a valid range. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
+		  const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+    { return __first._M_valid_range(__last); }
 } // namespace __gnu_debug
 
 #include <debug/safe_local_iterator.tcc>
Index: include/debug/safe_sequence.h
===================================================================
--- include/debug/safe_sequence.h	(revision 223630)
+++ include/debug/safe_sequence.h	(working copy)
@@ -29,7 +29,7 @@
 #ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_H
 #define _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 1
 
-#include <debug/debug.h>
+#include <debug/assertions.h>
 #include <debug/macros.h>
 #include <debug/functions.h>
 #include <debug/safe_base.h>
@@ -36,9 +36,6 @@
 
 namespace __gnu_debug
 {
-  template<typename _Iterator, typename _Sequence>
-    class _Safe_iterator;
-
   /** A simple function object that returns true if the passed-in
    *  value is not equal to the stored value. It saves typing over
    *  using both bind1st and not_equal.
Index: include/debug/safe_unordered_container.h
===================================================================
--- include/debug/safe_unordered_container.h	(revision 223630)
+++ include/debug/safe_unordered_container.h	(working copy)
@@ -29,7 +29,7 @@
 #ifndef _GLIBCXX_DEBUG_SAFE_UNORDERED_CONTAINER_H
 #define _GLIBCXX_DEBUG_SAFE_UNORDERED_CONTAINER_H 1
 
-#include <debug/debug.h>
+#include <debug/assertions.h>
 #include <debug/macros.h>
 #include <debug/functions.h>
 #include <debug/safe_unordered_base.h>
Index: include/debug/string
===================================================================
--- include/debug/string	(revision 223630)
+++ include/debug/string	(working copy)
@@ -1158,4 +1158,6 @@
 
 } // namespace __gnu_debug
 
+#include <debug/functions.tcc>
+
 #endif
Index: include/debug/vector
===================================================================
--- include/debug/vector	(revision 223630)
+++ include/debug/vector	(working copy)
@@ -742,8 +742,7 @@
     {
       size_t
       operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
-      { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
-	  (__b._M_base()); }
+      { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()(__b); }
     };
 #endif
 
@@ -762,4 +761,6 @@
     { };
 }
 
+#include <debug/functions.tcc>
+
 #endif
Index: src/c++11/debug.cc
===================================================================
--- src/c++11/debug.cc	(revision 223630)
+++ src/c++11/debug.cc	(working copy)
@@ -519,8 +519,123 @@
     if (_M_local_iterators == __it)
       _M_local_iterators = __it->_M_next;
   }
+}
 
+namespace
+{
   void
+  print_type(const __gnu_debug::_Error_formatter* __formatter,
+	     const type_info* __info,
+	     const char* __unknown_name)
+  {
+    if (!__info)
+      __formatter->_M_print_word(__unknown_name);
+    else
+      {
+	int __status;
+	char* __demangled_name =
+	  __cxxabiv1::__cxa_demangle(__info->name(), NULL, NULL, &__status);
+	__formatter->_M_print_word(__status == 0
+				   ? __demangled_name : __info->name());
+	free(__demangled_name);
+      }
+  }
+
+  bool
+  print_field(
+    const __gnu_debug::_Error_formatter* __formatter,
+    const char* __name,
+    const __gnu_debug::_Error_formatter::_Parameter::_Type& __variant)
+  {
+    if (strcmp(__name, "name") == 0)
+      {
+	assert(__variant._M_name);
+	__formatter->_M_print_word(__variant._M_name);
+      }
+    else if (strcmp(__name, "type") == 0)
+      print_type(__formatter, __variant._M_type, "<unknown type>");
+    else
+      return false;
+
+    return true;
+  }
+
+  bool
+  print_field(
+    const __gnu_debug::_Error_formatter* __formatter,
+    const char* __name,
+    const __gnu_debug::_Error_formatter::_Parameter::_Instance& __variant)
+  {
+    const __gnu_debug::_Error_formatter::_Parameter::_Type& __type = __variant;
+    if (print_field(__formatter, __name, __type))
+      { }
+    else if (strcmp(__name, "address") == 0)
+      {
+	const int __bufsize = 64;
+	char __buf[__bufsize];
+	__formatter->_M_format_word(__buf, __bufsize, "%p",
+				    __variant._M_address);
+	__formatter->_M_print_word(__buf);
+      }
+    else
+      return false;
+
+    return true;
+  }
+
+  void
+  print_description(
+	const __gnu_debug::_Error_formatter* __formatter,
+	const __gnu_debug::_Error_formatter::_Parameter::_Type& __variant)
+  {
+    if (__variant._M_name)
+      {
+	const int __bufsize = 64;
+	char __buf[__bufsize];
+	__formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
+				    __variant._M_name);
+	__formatter->_M_print_word(__buf);
+      }
+
+    if (__variant._M_type)
+      {
+	__formatter->_M_print_word("  type = ");
+	print_type(__formatter, __variant._M_type, "<unknown type>");
+	__formatter->_M_print_word(";\n");
+      }
+  }
+
+
+  void
+  print_description(
+	const __gnu_debug::_Error_formatter* __formatter,
+	const __gnu_debug::_Error_formatter::_Parameter::_Instance& __variant)
+  {
+    const int __bufsize = 64;
+    char __buf[__bufsize];
+
+    if (__variant._M_name)
+      {
+	__formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
+				    __variant._M_name);
+	__formatter->_M_print_word(__buf);
+      }
+
+    __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
+				__variant._M_address);
+    __formatter->_M_print_word(__buf);
+
+    if (__variant._M_type)
+      {
+	__formatter->_M_print_word("  type = ");
+	print_type(__formatter, __variant._M_type, "<unknown type>");
+      }
+  }
+}
+
+namespace __gnu_debug
+{
+  void
   _Error_formatter::_Parameter::
   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
   {
@@ -531,20 +646,8 @@
     switch (_M_kind)
     {
     case __iterator:
-      if (strcmp(__name, "name") == 0)
-	{
-	  assert(_M_variant._M_iterator._M_name);
-	  __formatter->_M_print_word(_M_variant._M_iterator._M_name);
-	}
-      else if (strcmp(__name, "address") == 0)
-	{
-	  __formatter->_M_format_word(__buf, __bufsize, "%p",
-				      _M_variant._M_iterator._M_address);
-	  __formatter->_M_print_word(__buf);
-	}
-      else if (strcmp(__name, "type") == 0)
-	__formatter->_M_print_type(_M_variant._M_iterator._M_type,
-				   "<unknown type>");
+      if (print_field(__formatter, __name, _M_variant._M_iterator))
+	{ }
       else if (strcmp(__name, "constness") == 0)
 	{
 	  static const char* __constness_names[__last_constness] =
@@ -579,28 +682,13 @@
 	  __formatter->_M_print_word(__buf);
 	}
       else if (strcmp(__name, "seq_type") == 0)
-	__formatter->_M_print_type(_M_variant._M_iterator._M_seq_type,
-				   "<unknown seq_type>");
+	print_type(__formatter, _M_variant._M_iterator._M_seq_type,
+		   "<unknown seq_type>");
       else
 	assert(false);
       break;
     case __sequence:
-      if (strcmp(__name, "name") == 0)
-	{
-	  assert(_M_variant._M_sequence._M_name);
-	  __formatter->_M_print_word(_M_variant._M_sequence._M_name);
-	}
-      else if (strcmp(__name, "address") == 0)
-	{
-	  assert(_M_variant._M_sequence._M_address);
-	  __formatter->_M_format_word(__buf, __bufsize, "%p",
-				      _M_variant._M_sequence._M_address);
-	  __formatter->_M_print_word(__buf);
-	}
-      else if (strcmp(__name, "type") == 0)
-	__formatter->_M_print_type(_M_variant._M_sequence._M_type,
-				   "<unknown type>");
-      else
+      if (!print_field(__formatter, __name, _M_variant._M_sequence))
 	assert(false);
       break;
     case __integer:
@@ -621,6 +709,14 @@
       else
 	assert(false);
       break;
+    case __instance:
+      if (!print_field(__formatter, __name, _M_variant._M_instance))
+	assert(false);
+      break;
+    case __iterator_value_type:
+      if (!print_field(__formatter, __name, _M_variant._M_iterator_value_type))
+	assert(false);
+      break;
     default:
       assert(false);
       break;
@@ -638,21 +734,10 @@
       {
       case __iterator:
 	__formatter->_M_print_word("iterator ");
-	if (_M_variant._M_iterator._M_name)
-	  {
-	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
-					_M_variant._M_iterator._M_name);
-	    __formatter->_M_print_word(__buf);
-	  }
+	print_description(__formatter, _M_variant._M_iterator);
 
-	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
-				    _M_variant._M_iterator._M_address);
-	__formatter->_M_print_word(__buf);
 	if (_M_variant._M_iterator._M_type)
 	  {
-	    __formatter->_M_print_word("type = ");
-	    _M_print_field(__formatter, "type");
-
 	    if (_M_variant._M_iterator._M_constness != __unknown_constness)
 	      {
 		__formatter->_M_print_word(" (");
@@ -687,25 +772,25 @@
 	break;
       case __sequence:
 	__formatter->_M_print_word("sequence ");
-	if (_M_variant._M_sequence._M_name)
-	  {
-	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
-					_M_variant._M_sequence._M_name);
-	    __formatter->_M_print_word(__buf);
-	  }
+	print_description(__formatter, _M_variant._M_sequence);
 
-	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
-				    _M_variant._M_sequence._M_address);
-	__formatter->_M_print_word(__buf);
+	if (_M_variant._M_sequence._M_type)
+	  __formatter->_M_print_word(";\n");
 
-	if (_M_variant._M_sequence._M_type)
-	  {
-	    __formatter->_M_print_word("  type = ");
-	    _M_print_field(__formatter, "type");
-	    __formatter->_M_print_word(";\n");
-	  }
 	__formatter->_M_print_word("}\n");
 	break;
+      case __instance:
+	__formatter->_M_print_word("instance ");
+	print_description(__formatter, _M_variant._M_instance);
+
+	if (_M_variant._M_instance._M_type)
+	  __formatter->_M_print_word(";\n");
+
+	break;
+      case __iterator_value_type:
+	__formatter->_M_print_word("iterator::value_type ");
+	print_description(__formatter, _M_variant._M_iterator_value_type);
+	break;
       default:
 	break;
       }
@@ -756,6 +841,8 @@
 	  {
 	  case _Parameter::__iterator:
 	  case _Parameter::__sequence:
+	  case _Parameter::__instance:
+	  case _Parameter::__iterator_value_type:
 	    if (!__has_noninteger_parameters)
 	      {
 		_M_first_line = true;
@@ -879,9 +966,9 @@
 
 	// Get the parameter number
 	assert(*__start >= '1' && *__start <= '9');
-	size_t __param = *__start - '0';
-	--__param;
-	assert(__param < _M_num_parameters);
+	size_t __param_index = *__start - '0' - 1;
+	assert(__param_index < _M_num_parameters);
+	const auto& __param = _M_parameters[__param_index];
 
 	// '.' separates the parameter number from the field
 	// name, if there is one.
@@ -891,14 +978,14 @@
 	    assert(*__start == ';');
 	    ++__start;
 	    __buf[0] = '\0';
-	    if (_M_parameters[__param]._M_kind == _Parameter::__integer)
+	    if (__param._M_kind == _Parameter::__integer)
 	      {
 		_M_format_word(__buf, __bufsize, "%ld",
-			       _M_parameters[__param]._M_variant._M_integer._M_value);
+			       __param._M_variant._M_integer._M_value);
 		_M_print_word(__buf);
 	      }
-	    else if (_M_parameters[__param]._M_kind == _Parameter::__string)
-	      _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
+	    else if (__param._M_kind == _Parameter::__string)
+	      _M_print_string(__param._M_variant._M_string._M_value);
 	    continue;
 	  }
 
@@ -916,27 +1003,11 @@
 	++__start;
 	__field[__field_idx] = 0;
 
-	_M_parameters[__param]._M_print_field(this, __field);
+	__param._M_print_field(this, __field);
       }
   }
 
   void
-  _Error_formatter::_M_print_type(const type_info* __info,
-				  const char* __unknown_name) const
-  {
-    if (!__info)
-      _M_print_word(__unknown_name);
-    else
-      {
-	int __status;
-	char* __demangled_name =
-	  __cxxabiv1::__cxa_demangle(__info->name(), NULL, NULL, &__status);
-	_M_print_word(__status == 0 ? __demangled_name : __info->name());
-	free(__demangled_name);
-      }
-  }
-
-  void
   _Error_formatter::_M_get_max_length() const throw ()
   {
     const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
Index: testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
===================================================================
--- testsuite/23_containers/array/tuple_interface/get_debug_neg.cc	(revision 223630)
+++ testsuite/23_containers/array/tuple_interface/get_debug_neg.cc	(working copy)
@@ -28,6 +28,6 @@
 int n2 = std::get<1>(std::move(a));
 int n3 = std::get<1>(ca);
 
-// { dg-error "static assertion failed" "" { target *-*-* } 271 }
-// { dg-error "static assertion failed" "" { target *-*-* } 280 }
-// { dg-error "static assertion failed" "" { target *-*-* } 288 }
+// { dg-error "static assertion failed" "" { target *-*-* } 272 }
+// { dg-error "static assertion failed" "" { target *-*-* } 281 }
+// { dg-error "static assertion failed" "" { target *-*-* } 289 }
Index: testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc
===================================================================
--- testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc	(revision 223630)
+++ testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc	(working copy)
@@ -23,4 +23,4 @@
 
 typedef std::tuple_element<1, std::array<int, 1>>::type type;
 
-// { dg-error "static assertion failed" "" { target *-*-* } 305 }
+// { dg-error "static assertion failed" "" { target *-*-* } 306 }

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