This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Reorganize and clean debug headers
- From: FranÃois Dumont <frs dot dumont at gmail dot com>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 20 Jan 2015 00:10:46 +0100
- Subject: Reorganize and clean debug headers
- Authentication-results: sourceware.org; auth=none
Hi
While working on new debug checks I came up with reorganizing
existing ones to limit as much as possible useless includes.
Tested under linux x86_64.
From the latest mails I saw on this mailing list I guess I must
wait, right ?
2015-01-20 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/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/formatter.h: Include typeinfo only if rtti enabled.
[_GLIBCXX_TYPEID]: New, use it throughout the file.
* 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
* include/debug/safe_unordered_container.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.
FranÃois
Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 219856)
+++ include/Makefile.am (working copy)
@@ -733,6 +733,7 @@
debug_builddir = ./debug
debug_headers = \
${debug_srcdir}/array \
+ ${debug_srcdir}/assertions.h \
${debug_srcdir}/bitset \
${debug_srcdir}/debug.h \
${debug_srcdir}/deque \
@@ -739,6 +740,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 219856)
+++ include/Makefile.in (working copy)
@@ -995,6 +995,7 @@
debug_builddir = ./debug
debug_headers = \
${debug_srcdir}/array \
+ ${debug_srcdir}/assertions.h \
${debug_srcdir}/bitset \
${debug_srcdir}/debug.h \
${debug_srcdir}/deque \
@@ -1001,6 +1002,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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ include/debug/formatter.h (working copy)
@@ -31,8 +31,18 @@
#include <bits/c++config.h>
#include <bits/cpp_type_traits.h>
-#include <typeinfo>
+#if __cpp_rtti
+# include <typeinfo>
+# define _GLIBCXX_TYPEID(_Type) &typeid(_Type)
+#else
+namespace std
+{
+ class type_info;
+}
+# define _GLIBCXX_TYPEID(_Type) 0
+#endif
+
namespace __gnu_debug
{
using std::type_info;
@@ -218,21 +228,13 @@
{
_M_variant._M_iterator._M_name = __name;
_M_variant._M_iterator._M_address = &__it;
-#if __cpp_rtti
- _M_variant._M_iterator._M_type = &typeid(__it);
-#else
- _M_variant._M_iterator._M_type = 0;
-#endif
+ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
_M_variant._M_iterator._M_constness =
std::__are_same<_Safe_iterator<_Iterator, _Sequence>,
typename _Sequence::iterator>::
__value ? __mutable_iterator : __const_iterator;
_M_variant._M_iterator._M_sequence = __it._M_get_sequence();
-#if __cpp_rtti
- _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
-#else
- _M_variant._M_iterator._M_seq_type = 0;
-#endif
+ _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
if (__it._M_singular())
_M_variant._M_iterator._M_state = __singular;
@@ -256,21 +258,13 @@
{
_M_variant._M_iterator._M_name = __name;
_M_variant._M_iterator._M_address = &__it;
-#if __cpp_rtti
- _M_variant._M_iterator._M_type = &typeid(__it);
-#else
- _M_variant._M_iterator._M_type = 0;
-#endif
+ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
_M_variant._M_iterator._M_constness =
std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>,
typename _Sequence::local_iterator>::
__value ? __mutable_iterator : __const_iterator;
_M_variant._M_iterator._M_sequence = __it._M_get_sequence();
-#if __cpp_rtti
- _M_variant._M_iterator._M_seq_type = &typeid(_Sequence);
-#else
- _M_variant._M_iterator._M_seq_type = 0;
-#endif
+ _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
if (__it._M_singular())
_M_variant._M_iterator._M_state = __singular;
@@ -291,11 +285,7 @@
{
_M_variant._M_iterator._M_name = __name;
_M_variant._M_iterator._M_address = &__it;
-#if __cpp_rtti
- _M_variant._M_iterator._M_type = &typeid(__it);
-#else
- _M_variant._M_iterator._M_type = 0;
-#endif
+ _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_sequence = 0;
@@ -308,11 +298,7 @@
{
_M_variant._M_iterator._M_name = __name;
_M_variant._M_iterator._M_address = &__it;
-#if __cpp_rtti
- _M_variant._M_iterator._M_type = &typeid(__it);
-#else
- _M_variant._M_iterator._M_type = 0;
-#endif
+ _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_sequence = 0;
@@ -325,11 +311,7 @@
{
_M_variant._M_iterator._M_name = __name;
_M_variant._M_iterator._M_address = &__it;
-#if __cpp_rtti
- _M_variant._M_iterator._M_type = &typeid(__it);
-#else
- _M_variant._M_iterator._M_type = 0;
-#endif
+ _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;
@@ -345,11 +327,7 @@
_M_variant._M_sequence._M_name = __name;
_M_variant._M_sequence._M_address =
static_cast<const _Sequence*>(&__seq);
-#if __cpp_rtti
- _M_variant._M_sequence._M_type = &typeid(_Sequence);
-#else
- _M_variant._M_sequence._M_type = 0;
-#endif
+ _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
}
template<typename _Sequence>
@@ -358,11 +336,7 @@
{
_M_variant._M_sequence._M_name = __name;
_M_variant._M_sequence._M_address = &__seq;
-#if __cpp_rtti
- _M_variant._M_sequence._M_type = &typeid(_Sequence);
-#else
- _M_variant._M_sequence._M_type = 0;
-#endif
+ _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
}
void
@@ -443,16 +417,16 @@
enum { __max_parameters = 9 };
- const char* _M_file;
- std::size_t _M_line;
- mutable _Parameter _M_parameters[__max_parameters];
- mutable std::size_t _M_num_parameters;
- mutable const char* _M_text;
- mutable std::size_t _M_max_length;
+ const char* _M_file;
+ std::size_t _M_line;
+ mutable _Parameter _M_parameters[__max_parameters];
+ mutable std::size_t _M_num_parameters;
+ mutable const char* _M_text;
+ mutable std::size_t _M_max_length;
enum { _M_indent = 4 } ;
- mutable std::size_t _M_column;
- mutable bool _M_first_line;
- mutable bool _M_wordwrap;
+ mutable std::size_t _M_column;
+ mutable bool _M_first_line;
+ mutable bool _M_wordwrap;
public:
static _Error_formatter
@@ -461,4 +435,6 @@
};
} // namespace __gnu_debug
+#undef _GLIBCXX_TYPEID
+
#endif
Index: include/debug/forward_list
===================================================================
--- include/debug/forward_list (revision 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ 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 219856)
+++ include/debug/vector (working copy)
@@ -738,8 +738,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
@@ -758,4 +757,6 @@
{ };
}
+#include <debug/functions.tcc>
+
#endif
Index: testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
===================================================================
--- testsuite/23_containers/array/tuple_interface/get_debug_neg.cc (revision 219856)
+++ 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 219856)
+++ 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 }