xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/debug/forward_list (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1// <forward_list> -*- C++ -*-
2
3// Copyright (C) 2010-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file debug/forward_list
26 *  This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_FORWARD_LIST
30#define _GLIBCXX_DEBUG_FORWARD_LIST 1
31
32#pragma GCC system_header
33
34#include <bits/c++config.h>
35namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
36  template<typename _Tp, typename _Allocator> class forward_list;
37} } // namespace std::__debug
38
39#include <forward_list>
40#include <debug/safe_sequence.h>
41#include <debug/safe_container.h>
42#include <debug/safe_iterator.h>
43
44// Special validity check for forward_list ranges.
45#define __glibcxx_check_valid_fl_range(_First,_Last,_Dist)		\
46_GLIBCXX_DEBUG_VERIFY(_First._M_valid_range(_Last, _Dist, false),	\
47		      _M_message(__gnu_debug::__msg_valid_range)	\
48		      ._M_iterator(_First, #_First)			\
49		      ._M_iterator(_Last, #_Last))
50
51namespace __gnu_debug
52{
53  /// Special iterators swap and invalidation for forward_list because of the
54  /// before_begin iterator.
55  template<typename _SafeSequence>
56    class _Safe_forward_list
57    : public _Safe_sequence<_SafeSequence>
58    {
59      _SafeSequence&
60      _M_this() noexcept
61      { return *static_cast<_SafeSequence*>(this); }
62
63      static void
64      _M_swap_aux(_Safe_sequence_base& __lhs,
65		  _Safe_iterator_base*& __lhs_iterators,
66		  _Safe_sequence_base& __rhs,
67		  _Safe_iterator_base*& __rhs_iterators);
68
69      void _M_swap_single(_Safe_sequence_base&) noexcept;
70
71    protected:
72      void
73      _M_invalidate_all()
74      {
75	using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
76	this->_M_invalidate_if([this](_Base_const_iterator __it)
77	{
78	  return __it != _M_this()._M_base().cbefore_begin()
79	    && __it != _M_this()._M_base().cend(); });
80      }
81
82      void _M_swap(_Safe_sequence_base&) noexcept;
83    };
84
85   template<typename _SafeSequence>
86    void
87    _Safe_forward_list<_SafeSequence>::
88    _M_swap_aux(_Safe_sequence_base& __lhs,
89		_Safe_iterator_base*& __lhs_iterators,
90		_Safe_sequence_base& __rhs,
91		_Safe_iterator_base*& __rhs_iterators)
92    {
93      using const_iterator = typename _SafeSequence::const_iterator;
94      _Safe_iterator_base* __bbegin_its = 0;
95      _Safe_iterator_base* __last_bbegin = 0;
96      _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
97
98      for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
99	{
100	  // Even iterator is cast to const_iterator, not a problem.
101	  _Safe_iterator_base* __victim_base = __iter;
102	  const_iterator* __victim =
103	    static_cast<const_iterator*>(__victim_base);
104	  __iter = __iter->_M_next;
105	  if (__victim->base() == __rseq._M_base().cbefore_begin())
106	    {
107	      __victim->_M_unlink();
108	      if (__lhs_iterators == __victim_base)
109		__lhs_iterators = __victim_base->_M_next;
110	      if (__bbegin_its)
111		{
112		  __victim_base->_M_next = __bbegin_its;
113		  __bbegin_its->_M_prior = __victim_base;
114		}
115	      else
116		__last_bbegin = __victim_base;
117	      __bbegin_its = __victim_base;
118	    }
119	  else
120	    __victim_base->_M_sequence = std::__addressof(__lhs);
121	}
122
123      if (__bbegin_its)
124	{
125	  if (__rhs_iterators)
126	    {
127	      __rhs_iterators->_M_prior = __last_bbegin;
128	      __last_bbegin->_M_next = __rhs_iterators;
129	    }
130	  __rhs_iterators = __bbegin_its;
131	}
132    }
133
134   template<typename _SafeSequence>
135    void
136    _Safe_forward_list<_SafeSequence>::
137    _M_swap_single(_Safe_sequence_base& __other) noexcept
138    {
139      std::swap(_M_this()._M_iterators, __other._M_iterators);
140      std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
141      // Useless, always 1 on forward_list
142      //std::swap(_M_this()_M_version, __other._M_version);
143      _Safe_iterator_base* __this_its = _M_this()._M_iterators;
144      _M_swap_aux(__other, __other._M_iterators,
145		  _M_this(), _M_this()._M_iterators);
146      _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
147      _M_swap_aux(__other, __other._M_const_iterators,
148		  _M_this(), _M_this()._M_const_iterators);
149      _M_swap_aux(_M_this(), __this_its,
150		  __other, __other._M_iterators);
151      _M_swap_aux(_M_this(), __this_const_its,
152		  __other, __other._M_const_iterators);
153    }
154
155  /* Special forward_list _M_swap version that does not swap the
156   * before-begin ownership.*/
157   template<typename _SafeSequence>
158    void
159    _Safe_forward_list<_SafeSequence>::
160    _M_swap(_Safe_sequence_base& __other) noexcept
161    {
162      // We need to lock both sequences to swap
163      using namespace __gnu_cxx;
164      __mutex *__this_mutex = &_M_this()._M_get_mutex();
165      __mutex *__other_mutex =
166	&static_cast<_SafeSequence&>(__other)._M_get_mutex();
167      if (__this_mutex == __other_mutex)
168	{
169	  __scoped_lock __lock(*__this_mutex);
170	  _M_swap_single(__other);
171	}
172      else
173	{
174	  __scoped_lock __l1(__this_mutex < __other_mutex
175			     ? *__this_mutex : *__other_mutex);
176	  __scoped_lock __l2(__this_mutex < __other_mutex
177			     ? *__other_mutex : *__this_mutex);
178	  _M_swap_single(__other);
179	}
180    }
181}
182
183namespace std _GLIBCXX_VISIBILITY(default)
184{
185namespace __debug
186{
187  /// Class std::forward_list with safety/checking/debug instrumentation.
188  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
189    class forward_list
190    : public __gnu_debug::_Safe_container<
191	forward_list<_Tp, _Alloc>, _Alloc, __gnu_debug::_Safe_forward_list>,
192      public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>
193    {
194      typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>		_Base;
195      typedef __gnu_debug::_Safe_container<
196	forward_list, _Alloc, __gnu_debug::_Safe_forward_list>	_Safe;
197
198      typedef typename _Base::iterator		_Base_iterator;
199      typedef typename _Base::const_iterator	_Base_const_iterator;
200
201      template<typename _ItT, typename _SeqT, typename _CatT>
202	friend class ::__gnu_debug::_Safe_iterator;
203
204    public:
205      typedef typename _Base::reference		reference;
206      typedef typename _Base::const_reference	const_reference;
207
208      typedef __gnu_debug::_Safe_iterator<
209	_Base_iterator, forward_list>		iterator;
210      typedef __gnu_debug::_Safe_iterator<
211	_Base_const_iterator, forward_list>	const_iterator;
212
213      typedef typename _Base::size_type		size_type;
214      typedef typename _Base::difference_type	difference_type;
215
216      typedef _Tp				value_type;
217      typedef typename _Base::allocator_type	allocator_type;
218      typedef typename _Base::pointer		pointer;
219      typedef typename _Base::const_pointer	const_pointer;
220
221      // 23.2.3.1 construct/copy/destroy:
222
223      forward_list() = default;
224
225      explicit
226      forward_list(const allocator_type& __al) noexcept
227      : _Base(__al) { }
228
229      forward_list(const forward_list& __list, const allocator_type& __al)
230      : _Base(__list, __al)
231      { }
232
233      forward_list(forward_list&& __list, const allocator_type& __al)
234	: _Safe(std::move(__list._M_safe()), __al),
235	  _Base(std::move(__list._M_base()), __al)
236      { }
237
238      explicit
239      forward_list(size_type __n, const allocator_type& __al = allocator_type())
240      : _Base(__n, __al)
241      { }
242
243      forward_list(size_type __n, const _Tp& __value,
244		   const allocator_type& __al = allocator_type())
245      : _Base(__n, __value, __al)
246      { }
247
248      template<typename _InputIterator,
249	       typename = std::_RequireInputIter<_InputIterator>>
250	forward_list(_InputIterator __first, _InputIterator __last,
251		     const allocator_type& __al = allocator_type())
252	: _Base(__gnu_debug::__base(
253		  __glibcxx_check_valid_constructor_range(__first, __last)),
254		__gnu_debug::__base(__last), __al)
255	{ }
256
257      forward_list(const forward_list&) = default;
258
259      forward_list(forward_list&&) = default;
260
261      forward_list(std::initializer_list<_Tp> __il,
262		   const allocator_type& __al = allocator_type())
263      : _Base(__il, __al)
264      { }
265
266      ~forward_list() = default;
267
268      forward_list&
269      operator=(const forward_list&) = default;
270
271      forward_list&
272      operator=(forward_list&&) = default;
273
274      forward_list&
275      operator=(std::initializer_list<_Tp> __il)
276      {
277	_M_base() = __il;
278	this->_M_invalidate_all();
279	return *this;
280      }
281
282      template<typename _InputIterator,
283	       typename = std::_RequireInputIter<_InputIterator>>
284	void
285	assign(_InputIterator __first, _InputIterator __last)
286	{
287	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
288	  __glibcxx_check_valid_range2(__first, __last, __dist);
289
290	  if (__dist.second >= __gnu_debug::__dp_sign)
291	    _Base::assign(__gnu_debug::__unsafe(__first),
292			  __gnu_debug::__unsafe(__last));
293	  else
294	    _Base::assign(__first, __last);
295
296	  this->_M_invalidate_all();
297	}
298
299      void
300      assign(size_type __n, const _Tp& __val)
301      {
302	_Base::assign(__n, __val);
303	this->_M_invalidate_all();
304      }
305
306      void
307      assign(std::initializer_list<_Tp> __il)
308      {
309	_Base::assign(__il);
310	this->_M_invalidate_all();
311      }
312
313      using _Base::get_allocator;
314
315      // iterators:
316
317      iterator
318      before_begin() noexcept
319      { return { _Base::before_begin(), this }; }
320
321      const_iterator
322      before_begin() const noexcept
323      { return { _Base::before_begin(), this }; }
324
325      iterator
326      begin() noexcept
327      { return { _Base::begin(), this }; }
328
329      const_iterator
330      begin() const noexcept
331      { return { _Base::begin(), this }; }
332
333      iterator
334      end() noexcept
335      { return { _Base::end(), this }; }
336
337      const_iterator
338      end() const noexcept
339      { return { _Base::end(), this }; }
340
341      const_iterator
342      cbegin() const noexcept
343      { return { _Base::cbegin(), this }; }
344
345      const_iterator
346      cbefore_begin() const noexcept
347      { return { _Base::cbefore_begin(), this }; }
348
349      const_iterator
350      cend() const noexcept
351      { return { _Base::cend(), this }; }
352
353      using _Base::empty;
354      using _Base::max_size;
355
356      // element access:
357
358      reference
359      front()
360      {
361	__glibcxx_check_nonempty();
362	return _Base::front();
363      }
364
365      const_reference
366      front() const
367      {
368	__glibcxx_check_nonempty();
369	return _Base::front();
370      }
371
372      // modifiers:
373
374      using _Base::emplace_front;
375      using _Base::push_front;
376
377      void
378      pop_front()
379      {
380	__glibcxx_check_nonempty();
381	this->_M_invalidate_if([this](_Base_const_iterator __it)
382	  { return __it == this->_M_base().cbegin(); });
383	_Base::pop_front();
384      }
385
386      template<typename... _Args>
387	iterator
388	emplace_after(const_iterator __pos, _Args&&... __args)
389	{
390	  __glibcxx_check_insert_after(__pos);
391	  return { _Base::emplace_after(__pos.base(),
392					std::forward<_Args>(__args)...),
393		   this };
394       	}
395
396      iterator
397      insert_after(const_iterator __pos, const _Tp& __val)
398      {
399	__glibcxx_check_insert_after(__pos);
400	return { _Base::insert_after(__pos.base(), __val), this };
401      }
402
403      iterator
404      insert_after(const_iterator __pos, _Tp&& __val)
405      {
406	__glibcxx_check_insert_after(__pos);
407	return { _Base::insert_after(__pos.base(), std::move(__val)), this };
408      }
409
410      iterator
411      insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
412      {
413	__glibcxx_check_insert_after(__pos);
414	return { _Base::insert_after(__pos.base(), __n, __val), this };
415      }
416
417      template<typename _InputIterator,
418	       typename = std::_RequireInputIter<_InputIterator>>
419	iterator
420	insert_after(const_iterator __pos,
421		     _InputIterator __first, _InputIterator __last)
422	{
423	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
424	  __glibcxx_check_insert_range_after(__pos, __first, __last, __dist);
425
426	  if (__dist.second >= __gnu_debug::__dp_sign)
427	    return
428	      {
429		_Base::insert_after(__pos.base(),
430				    __gnu_debug::__unsafe(__first),
431				    __gnu_debug::__unsafe(__last)),
432		this
433	      };
434	  else
435	    return { _Base::insert_after(__pos.base(), __first, __last), this };
436	}
437
438      iterator
439      insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
440      {
441	__glibcxx_check_insert_after(__pos);
442	return { _Base::insert_after(__pos.base(), __il), this };
443      }
444
445    private:
446      _Base_iterator
447      _M_erase_after(_Base_const_iterator __pos)
448      {
449	_Base_const_iterator __next = std::next(__pos);
450	this->_M_invalidate_if([__next](_Base_const_iterator __it)
451	  { return __it == __next; });
452	return _Base::erase_after(__pos);
453      }
454    public:
455      iterator
456      erase_after(const_iterator __pos)
457      {
458	__glibcxx_check_erase_after(__pos);
459	return { _M_erase_after(__pos.base()), this };
460      }
461
462      iterator
463      erase_after(const_iterator __pos, const_iterator __last)
464      {
465	__glibcxx_check_erase_range_after(__pos, __last);
466	for (_Base_const_iterator __victim = std::next(__pos.base());
467	    __victim != __last.base(); ++__victim)
468	  {
469	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::cend(),
470				  _M_message(__gnu_debug::__msg_valid_range2)
471				  ._M_sequence(*this, "this")
472				  ._M_iterator(__pos, "pos")
473				  ._M_iterator(__last, "last"));
474	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
475	      { return __it == __victim; });
476	  }
477
478	return { _Base::erase_after(__pos.base(), __last.base()), this };
479      }
480
481      void
482      swap(forward_list& __list)
483	noexcept( noexcept(declval<_Base&>().swap(__list)) )
484      {
485	_Safe::_M_swap(__list);
486	_Base::swap(__list);
487      }
488
489      void
490      resize(size_type __sz)
491      {
492	this->_M_detach_singular();
493
494	// if __sz < size(), invalidate all iterators in [begin+__sz, end()
495	_Base_iterator __victim = _Base::begin();
496	_Base_iterator __end = _Base::end();
497	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
498	  ++__victim;
499
500	for (; __victim != __end; ++__victim)
501	  {
502	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
503	      { return __it == __victim; });
504	  }
505
506	__try
507	  {
508	    _Base::resize(__sz);
509	  }
510	__catch(...)
511	  {
512	    this->_M_revalidate_singular();
513	    __throw_exception_again;
514	  }
515      }
516
517      void
518      resize(size_type __sz, const value_type& __val)
519      {
520	this->_M_detach_singular();
521
522	// if __sz < size(), invalidate all iterators in [begin+__sz, end())
523	_Base_iterator __victim = _Base::begin();
524	_Base_iterator __end = _Base::end();
525	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
526	  ++__victim;
527
528	for (; __victim != __end; ++__victim)
529	  {
530	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
531	      { return __it == __victim; });
532	  }
533
534	__try
535	  {
536	    _Base::resize(__sz, __val);
537	  }
538	__catch(...)
539	  {
540	    this->_M_revalidate_singular();
541	    __throw_exception_again;
542	  }
543      }
544
545      void
546      clear() noexcept
547      {
548	_Base::clear();
549	this->_M_invalidate_all();
550      }
551
552      // 23.2.3.5 forward_list operations:
553      void
554      splice_after(const_iterator __pos, forward_list&& __list)
555      {
556	__glibcxx_check_insert_after(__pos);
557	_GLIBCXX_DEBUG_VERIFY(std::__addressof(__list) != this,
558			      _M_message(__gnu_debug::__msg_self_splice)
559			      ._M_sequence(*this, "this"));
560	_GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
561			      _M_message(__gnu_debug::__msg_splice_alloc)
562			      ._M_sequence(*this)
563			      ._M_sequence(__list, "__list"));
564	this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
565	  {
566	    return __it != __list._M_base().cbefore_begin()
567		   && __it != __list._M_base().end();
568	  });
569	_Base::splice_after(__pos.base(), std::move(__list._M_base()));
570      }
571
572      void
573      splice_after(const_iterator __pos, forward_list& __list)
574      { splice_after(__pos, std::move(__list)); }
575
576      void
577      splice_after(const_iterator __pos, forward_list&& __list,
578		   const_iterator __i)
579      {
580	__glibcxx_check_insert_after(__pos);
581	_GLIBCXX_DEBUG_VERIFY(__i._M_before_dereferenceable(),
582			      _M_message(__gnu_debug::__msg_splice_bad)
583			      ._M_iterator(__i, "__i"));
584	_GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(std::__addressof(__list)),
585			      _M_message(__gnu_debug::__msg_splice_other)
586			      ._M_iterator(__i, "__i")
587			      ._M_sequence(__list, "__list"));
588	_GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
589			      _M_message(__gnu_debug::__msg_splice_alloc)
590			      ._M_sequence(*this)
591			      ._M_sequence(__list, "__list"));
592
593	// _GLIBCXX_RESOLVE_LIB_DEFECTS
594	// 250. splicing invalidates iterators
595	_Base_const_iterator __next = std::next(__i.base());
596	this->_M_transfer_from_if(__list, [__next](_Base_const_iterator __it)
597	  { return __it == __next; });
598	_Base::splice_after(__pos.base(), std::move(__list._M_base()),
599			    __i.base());
600      }
601
602      void
603      splice_after(const_iterator __pos, forward_list& __list,
604		   const_iterator __i)
605      { splice_after(__pos, std::move(__list), __i); }
606
607      void
608      splice_after(const_iterator __pos, forward_list&& __list,
609		   const_iterator __before, const_iterator __last)
610      {
611	typename __gnu_debug::_Distance_traits<const_iterator>::__type __dist;
612	auto __listptr = std::__addressof(__list);
613	__glibcxx_check_insert_after(__pos);
614	__glibcxx_check_valid_fl_range(__before, __last, __dist);
615	_GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(__listptr),
616			      _M_message(__gnu_debug::__msg_splice_other)
617			      ._M_sequence(__list, "list")
618			      ._M_iterator(__before, "before"));
619	_GLIBCXX_DEBUG_VERIFY(__before._M_dereferenceable()
620			      || __before._M_is_before_begin(),
621			      _M_message(__gnu_debug::__msg_valid_range2)
622			      ._M_sequence(__list, "list")
623			      ._M_iterator(__before, "before")
624			      ._M_iterator(__last, "last"));
625	_GLIBCXX_DEBUG_VERIFY(__before != __last,
626			      _M_message(__gnu_debug::__msg_valid_range2)
627			      ._M_sequence(__list, "list")
628			      ._M_iterator(__before, "before")
629			      ._M_iterator(__last, "last"));
630	_GLIBCXX_DEBUG_VERIFY(__list.get_allocator() == this->get_allocator(),
631			      _M_message(__gnu_debug::__msg_splice_alloc)
632			      ._M_sequence(*this)
633			      ._M_sequence(__list, "__list"));
634
635	for (_Base_const_iterator __tmp = std::next(__before.base());
636	     __tmp != __last.base(); ++__tmp)
637	  {
638	    _GLIBCXX_DEBUG_VERIFY(__tmp != __list._M_base().end(),
639				  _M_message(__gnu_debug::__msg_valid_range2)
640				  ._M_sequence(__list, "list")
641				  ._M_iterator(__before, "before")
642				  ._M_iterator(__last, "last"));
643	    _GLIBCXX_DEBUG_VERIFY(__listptr != this || __tmp != __pos.base(),
644				  _M_message(__gnu_debug::__msg_splice_overlap)
645				  ._M_iterator(__tmp, "position")
646				  ._M_iterator(__before, "before")
647				  ._M_iterator(__last, "last"));
648	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
649	    // 250. splicing invalidates iterators
650	    this->_M_transfer_from_if(__list, [__tmp](_Base_const_iterator __it)
651	      { return __it == __tmp; });
652	  }
653
654	_Base::splice_after(__pos.base(), std::move(__list._M_base()),
655			    __before.base(), __last.base());
656      }
657
658      void
659      splice_after(const_iterator __pos, forward_list& __list,
660		   const_iterator __before, const_iterator __last)
661      { splice_after(__pos, std::move(__list), __before, __last); }
662
663    private:
664#if __cplusplus > 201703L
665      using __remove_return_type = size_type;
666# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \
667      __attribute__((__abi_tag__("__cxx20")))
668# define _GLIBCXX20_ONLY(__expr) __expr
669#else
670      using __remove_return_type = void;
671# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
672# define _GLIBCXX20_ONLY(__expr)
673#endif
674
675    public:
676      _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
677      __remove_return_type
678      remove(const _Tp& __val)
679      {
680	if (!this->_M_iterators && !this->_M_const_iterators)
681	  return _Base::remove(__val);
682
683	size_type __removed __attribute__((__unused__)) = 0;
684	_Base_iterator __x = _Base::before_begin();
685	_Base_iterator __old = __x++;
686	_Base_iterator __extra = _Base::end();
687	while (__x != _Base::end())
688	  {
689	    if (*__x == __val)
690	      {
691		if (std::__addressof(*__x) != std::__addressof(__val))
692		  {
693		    __x = _M_erase_after(__old);
694		    _GLIBCXX20_ONLY( __removed++ );
695		    continue;
696		  }
697		else
698		  __extra = __old;
699	      }
700	    __old = __x++;
701	  }
702
703	if (__extra != _Base::end())
704	  {
705	    this->_M_erase_after(__extra);
706	    _GLIBCXX20_ONLY( __removed++ );
707	  }
708
709	return _GLIBCXX20_ONLY( __removed );
710      }
711
712      template<typename _Pred>
713	__remove_return_type
714	remove_if(_Pred __pred)
715	{
716	  if (!this->_M_iterators && !this->_M_const_iterators)
717	    return _Base::remove_if(__pred);
718
719	  size_type __removed __attribute__((__unused__)) = 0;
720	  _Base_iterator __x = _Base::before_begin();
721	  _Base_iterator __old = __x++;
722	  while (__x != _Base::end())
723	    if (__pred(*__x))
724	      {
725		__x = _M_erase_after(__old);
726		_GLIBCXX20_ONLY( __removed++ );
727	      }
728	    else
729	      __old = __x++;
730
731	  return _GLIBCXX20_ONLY( __removed );
732	}
733
734      _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
735      __remove_return_type
736      unique()
737      { return unique(std::equal_to<_Tp>()); }
738
739      template<typename _BinPred>
740	__remove_return_type
741	unique(_BinPred __binary_pred)
742	{
743	  if (!this->_M_iterators && !this->_M_const_iterators)
744	    return _Base::unique(__binary_pred);
745
746	  _Base_iterator __first = _Base::begin();
747	  _Base_iterator __last = _Base::end();
748	  if (__first == __last)
749	    return _GLIBCXX20_ONLY(0);
750
751	  size_type __removed __attribute__((__unused__)) = 0;
752	  _Base_iterator __next = std::next(__first);
753	  while (__next != __last)
754	    {
755	      if (__binary_pred(*__first, *__next))
756		{
757		  __next = _M_erase_after(__first);
758		  _GLIBCXX20_ONLY( __removed++ );
759		}
760	      else
761		__first = __next++;
762	    }
763
764	  return _GLIBCXX20_ONLY( __removed );
765	}
766
767#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG
768#undef _GLIBCXX20_ONLY
769
770      void
771      merge(forward_list&& __list)
772      {
773	if (this != std::__addressof(__list))
774	{
775	  __glibcxx_check_sorted(_Base::begin(), _Base::end());
776	  __glibcxx_check_sorted(__list._M_base().begin(),
777				 __list._M_base().end());
778	  this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it)
779	    {
780	      return __it != __list._M_base().cbefore_begin()
781		     && __it != __list._M_base().cend();
782	    });
783	  _Base::merge(std::move(__list._M_base()));
784	}
785      }
786
787      void
788      merge(forward_list& __list)
789      { merge(std::move(__list)); }
790
791      template<typename _Comp>
792	void
793	merge(forward_list&& __list, _Comp __comp)
794	{
795	  if (this != std::__addressof(__list))
796	  {
797	    __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
798	    __glibcxx_check_sorted_pred(__list._M_base().begin(),
799					__list._M_base().end(), __comp);
800	    this->_M_transfer_from_if(__list,
801				      [&__list](_Base_const_iterator __it)
802	      {
803		return __it != __list._M_base().cbefore_begin()
804		       && __it != __list._M_base().cend();
805	      });
806	    _Base::merge(std::move(__list._M_base()), __comp);
807	  }
808	}
809
810      template<typename _Comp>
811	void
812	merge(forward_list& __list, _Comp __comp)
813	{ merge(std::move(__list), __comp); }
814
815      using _Base::sort;
816      using _Base::reverse;
817
818      _Base&
819      _M_base() noexcept { return *this; }
820
821      const _Base&
822      _M_base() const noexcept { return *this; }
823    };
824
825#if __cpp_deduction_guides >= 201606
826  template<typename _InputIterator, typename _ValT
827	     = typename iterator_traits<_InputIterator>::value_type,
828	   typename _Allocator = allocator<_ValT>,
829	   typename = _RequireInputIter<_InputIterator>,
830	   typename = _RequireAllocator<_Allocator>>
831    forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator())
832      -> forward_list<_ValT, _Allocator>;
833#endif
834
835  template<typename _Tp, typename _Alloc>
836    bool
837    operator==(const forward_list<_Tp, _Alloc>& __lx,
838	       const forward_list<_Tp, _Alloc>& __ly)
839    { return __lx._M_base() == __ly._M_base(); }
840
841#if __cpp_lib_three_way_comparison
842  template<typename _Tp, typename _Alloc>
843    constexpr __detail::__synth3way_t<_Tp>
844    operator<=>(const forward_list<_Tp, _Alloc>& __x,
845		const forward_list<_Tp, _Alloc>& __y)
846    { return __x._M_base() <=> __y._M_base(); }
847#else
848  template<typename _Tp, typename _Alloc>
849    inline bool
850    operator<(const forward_list<_Tp, _Alloc>& __lx,
851	      const forward_list<_Tp, _Alloc>& __ly)
852    { return __lx._M_base() < __ly._M_base(); }
853
854  template<typename _Tp, typename _Alloc>
855    inline bool
856    operator!=(const forward_list<_Tp, _Alloc>& __lx,
857	       const forward_list<_Tp, _Alloc>& __ly)
858    { return !(__lx == __ly); }
859
860  /// Based on operator<
861  template<typename _Tp, typename _Alloc>
862    inline bool
863    operator>(const forward_list<_Tp, _Alloc>& __lx,
864	      const forward_list<_Tp, _Alloc>& __ly)
865    { return (__ly < __lx); }
866
867  /// Based on operator<
868  template<typename _Tp, typename _Alloc>
869    inline bool
870    operator>=(const forward_list<_Tp, _Alloc>& __lx,
871	       const forward_list<_Tp, _Alloc>& __ly)
872    { return !(__lx < __ly); }
873
874  /// Based on operator<
875  template<typename _Tp, typename _Alloc>
876    inline bool
877    operator<=(const forward_list<_Tp, _Alloc>& __lx,
878	       const forward_list<_Tp, _Alloc>& __ly)
879    { return !(__ly < __lx); }
880#endif // three-way comparison
881
882  /// See std::forward_list::swap().
883  template<typename _Tp, typename _Alloc>
884    inline void
885    swap(forward_list<_Tp, _Alloc>& __lx, forward_list<_Tp, _Alloc>& __ly)
886    noexcept(noexcept(__lx.swap(__ly)))
887    { __lx.swap(__ly); }
888
889} // namespace __debug
890} // namespace std
891
892namespace __gnu_debug
893{
894  template<typename _Tp, typename _Alloc>
895    struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
896    {
897      typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
898
899      template<typename _Iterator>
900	static bool
901	_S_Is(const _Safe_iterator<_Iterator, _Sequence>& __it)
902	{
903	  return
904	    __it.base() == __it._M_get_sequence()->_M_base().before_begin();
905	}
906
907      template<typename _Iterator>
908	static bool
909	_S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
910	{ return _S_Is(__it); }
911    };
912
913  template<typename _Tp, typename _Alloc>
914    struct _Sequence_traits<std::__debug::forward_list<_Tp, _Alloc> >
915    {
916      typedef typename std::__debug::forward_list<_Tp, _Alloc>::iterator _It;
917
918      static typename _Distance_traits<_It>::__type
919      _S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
920      {
921	return __seq.empty()
922	  ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_sign);
923      }
924    };
925
926#ifndef _GLIBCXX_DEBUG_PEDANTIC
927  template<class _Tp, class _Alloc>
928    struct _Insert_range_from_self_is_safe<
929      std::__debug::forward_list<_Tp, _Alloc> >
930    { enum { __value = 1 }; };
931#endif
932}
933
934#endif
935