1// Debugging string implementation -*- C++ -*-
2
3// Copyright (C) 2003-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/string
26 *  This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_STRING
30#define _GLIBCXX_DEBUG_STRING 1
31
32#pragma GCC system_header
33
34#include <string>
35#include <debug/safe_sequence.h>
36#include <debug/safe_container.h>
37#include <debug/safe_iterator.h>
38
39#define _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_Cond,_File,_Line,_Func)	\
40  if (! (_Cond))							\
41    __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func)		\
42      ._M_message(#_Cond)._M_error()
43
44namespace __gnu_debug
45{
46  /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
47  template<typename _CharT, typename _Integer>
48    inline const _CharT*
49    __check_string(const _CharT* __s,
50		   _Integer __n __attribute__((__unused__)),
51		   const char* __file __attribute__((__unused__)),
52		   unsigned int __line __attribute__((__unused__)),
53		   const char* __function __attribute__((__unused__)))
54    {
55#ifdef _GLIBCXX_DEBUG_PEDANTIC
56      _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0 || __n == 0,
57					__file, __line, __function);
58#endif
59      return __s;
60    }
61
62  /** Checks that __s is non-NULL and then returns __s. */
63  template<typename _CharT>
64    inline const _CharT*
65    __check_string(const _CharT* __s,
66		   const char* __file __attribute__((__unused__)),
67		   unsigned int __line __attribute__((__unused__)),
68		   const char* __function __attribute__((__unused__)))
69    {
70#ifdef _GLIBCXX_DEBUG_PEDANTIC
71      _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0,
72					__file, __line, __function);
73#endif
74      return __s;
75    }
76
77#define __glibcxx_check_string_n_constructor(_Str, _Size) \
78  __check_string(_Str, _Size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
79
80#define __glibcxx_check_string_constructor(_Str) \
81  __check_string(_Str, __FILE__, __LINE__, __PRETTY_FUNCTION__)
82
83  /// Class std::basic_string with safety/checking/debug instrumentation.
84  template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
85	   typename _Allocator = std::allocator<_CharT> >
86    class basic_string
87      : public __gnu_debug::_Safe_container<
88	  basic_string<_CharT, _Traits, _Allocator>,
89	  _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>,
90	public std::basic_string<_CharT, _Traits, _Allocator>
91    {
92      typedef std::basic_string<_CharT, _Traits, _Allocator>	_Base;
93      typedef __gnu_debug::_Safe_container<
94	basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>
95      _Safe;
96
97      template<typename _ItT, typename _SeqT, typename _CatT>
98	friend class ::__gnu_debug::_Safe_iterator;
99
100      // type used for positions in insert, erase etc.
101      typedef __gnu_debug::_Safe_iterator<
102	typename _Base::__const_iterator, basic_string> __const_iterator;
103
104    public:
105      // types:
106      typedef _Traits					traits_type;
107      typedef typename _Traits::char_type		value_type;
108      typedef _Allocator				allocator_type;
109      typedef typename _Base::size_type			size_type;
110      typedef typename _Base::difference_type		difference_type;
111      typedef typename _Base::reference			reference;
112      typedef typename _Base::const_reference		const_reference;
113      typedef typename _Base::pointer			pointer;
114      typedef typename _Base::const_pointer		const_pointer;
115
116      typedef __gnu_debug::_Safe_iterator<
117	typename _Base::iterator, basic_string>		iterator;
118      typedef __gnu_debug::_Safe_iterator<
119	typename _Base::const_iterator, basic_string>	const_iterator;
120
121      typedef std::reverse_iterator<iterator>		reverse_iterator;
122      typedef std::reverse_iterator<const_iterator>	const_reverse_iterator;
123
124      using _Base::npos;
125
126      basic_string()
127	_GLIBCXX_NOEXCEPT_IF(std::is_nothrow_default_constructible<_Base>::value)
128	: _Base() { }
129
130      // 21.3.1 construct/copy/destroy:
131      explicit
132      basic_string(const _Allocator& __a) _GLIBCXX_NOEXCEPT
133      : _Base(__a) { }
134
135#if __cplusplus < 201103L
136      basic_string(const basic_string& __str)
137      : _Base(__str) { }
138
139      ~basic_string() { }
140#else
141      basic_string(const basic_string&) = default;
142      basic_string(basic_string&&) = default;
143
144      basic_string(std::initializer_list<_CharT> __l,
145		   const _Allocator& __a = _Allocator())
146      : _Base(__l, __a)
147      { }
148
149#if _GLIBCXX_USE_CXX11_ABI
150      basic_string(const basic_string& __s, const _Allocator& __a)
151      : _Base(__s, __a) { }
152
153      basic_string(basic_string&& __s, const _Allocator& __a)
154      : _Base(std::move(__s), __a) { }
155#endif
156
157      ~basic_string() = default;
158
159      // Provides conversion from a normal-mode string to a debug-mode string
160      basic_string(_Base&& __base) noexcept
161      : _Base(std::move(__base)) { }
162#endif // C++11
163
164      // Provides conversion from a normal-mode string to a debug-mode string
165      basic_string(const _Base& __base)
166      : _Base(__base) { }
167
168      // _GLIBCXX_RESOLVE_LIB_DEFECTS
169      // 42. string ctors specify wrong default allocator
170      basic_string(const basic_string& __str, size_type __pos,
171		   size_type __n = _Base::npos,
172		   const _Allocator& __a = _Allocator())
173      : _Base(__str, __pos, __n, __a) { }
174
175      basic_string(const _CharT* __s, size_type __n,
176		   const _Allocator& __a = _Allocator())
177      : _Base(__glibcxx_check_string_n_constructor(__s, __n), __n, __a) { }
178
179      basic_string(const _CharT* __s, const _Allocator& __a = _Allocator())
180      : _Base(__glibcxx_check_string_constructor(__s), __a)
181      { this->assign(__s); }
182
183      basic_string(size_type __n, _CharT __c,
184		   const _Allocator& __a = _Allocator())
185      : _Base(__n, __c, __a) { }
186
187      template<typename _InputIterator>
188	basic_string(_InputIterator __begin, _InputIterator __end,
189		     const _Allocator& __a = _Allocator())
190	: _Base(__gnu_debug::__base(
191		  __glibcxx_check_valid_constructor_range(__begin, __end)),
192		__gnu_debug::__base(__end), __a) { }
193
194#if __cplusplus < 201103L
195      basic_string&
196      operator=(const basic_string& __str)
197      {
198	this->_M_safe() = __str;
199	_M_base() = __str;
200	return *this;
201      }
202#else
203      basic_string&
204      operator=(const basic_string&) = default;
205
206      basic_string&
207      operator=(basic_string&&) = default;
208#endif
209
210      basic_string&
211      operator=(const _CharT* __s)
212      {
213	__glibcxx_check_string(__s);
214	_M_base() = __s;
215	this->_M_invalidate_all();
216	return *this;
217      }
218
219      basic_string&
220      operator=(_CharT __c)
221      {
222	_M_base() = __c;
223	this->_M_invalidate_all();
224	return *this;
225      }
226
227#if __cplusplus >= 201103L
228      basic_string&
229      operator=(std::initializer_list<_CharT> __l)
230      {
231	_M_base() = __l;
232	this->_M_invalidate_all();
233	return *this;
234      }
235#endif // C++11
236
237      // 21.3.2 iterators:
238      iterator
239      begin() // _GLIBCXX_NOEXCEPT
240      { return iterator(_Base::begin(), this); }
241
242      const_iterator
243      begin() const _GLIBCXX_NOEXCEPT
244      { return const_iterator(_Base::begin(), this); }
245
246      iterator
247      end() // _GLIBCXX_NOEXCEPT
248      { return iterator(_Base::end(), this); }
249
250      const_iterator
251      end() const _GLIBCXX_NOEXCEPT
252      { return const_iterator(_Base::end(), this); }
253
254      reverse_iterator
255      rbegin() // _GLIBCXX_NOEXCEPT
256      { return reverse_iterator(end()); }
257
258      const_reverse_iterator
259      rbegin() const _GLIBCXX_NOEXCEPT
260      { return const_reverse_iterator(end()); }
261
262      reverse_iterator
263      rend() // _GLIBCXX_NOEXCEPT
264      { return reverse_iterator(begin()); }
265
266      const_reverse_iterator
267      rend() const _GLIBCXX_NOEXCEPT
268      { return const_reverse_iterator(begin()); }
269
270#if __cplusplus >= 201103L
271      const_iterator
272      cbegin() const noexcept
273      { return const_iterator(_Base::begin(), this); }
274
275      const_iterator
276      cend() const noexcept
277      { return const_iterator(_Base::end(), this); }
278
279      const_reverse_iterator
280      crbegin() const noexcept
281      { return const_reverse_iterator(end()); }
282
283      const_reverse_iterator
284      crend() const noexcept
285      { return const_reverse_iterator(begin()); }
286#endif
287
288      // 21.3.3 capacity:
289      using _Base::size;
290      using _Base::length;
291      using _Base::max_size;
292
293      void
294      resize(size_type __n, _CharT __c)
295      {
296	_Base::resize(__n, __c);
297	this->_M_invalidate_all();
298      }
299
300      void
301      resize(size_type __n)
302      { this->resize(__n, _CharT()); }
303
304#if __cplusplus >= 201103L
305      void
306      shrink_to_fit() noexcept
307      {
308	if (capacity() > size())
309	  {
310	    __try
311	      {
312		reserve(0);
313		this->_M_invalidate_all();
314	      }
315	    __catch(...)
316	      { }
317	  }
318      }
319#endif
320
321      using _Base::capacity;
322      using _Base::reserve;
323
324      void
325      clear() // _GLIBCXX_NOEXCEPT
326      {
327	_Base::clear();
328	this->_M_invalidate_all();
329      }
330
331      using _Base::empty;
332
333      // 21.3.4 element access:
334      const_reference
335      operator[](size_type __pos) const _GLIBCXX_NOEXCEPT
336      {
337	_GLIBCXX_DEBUG_VERIFY(__pos <= this->size(),
338			      _M_message(__gnu_debug::__msg_subscript_oob)
339			      ._M_sequence(*this, "this")
340			      ._M_integer(__pos, "__pos")
341			      ._M_integer(this->size(), "size"));
342	return _M_base()[__pos];
343      }
344
345      reference
346      operator[](size_type __pos) // _GLIBCXX_NOEXCEPT
347      {
348#if __cplusplus < 201103L && defined(_GLIBCXX_DEBUG_PEDANTIC)
349	__glibcxx_check_subscript(__pos);
350#else
351	// as an extension v3 allows s[s.size()] when s is non-const.
352	_GLIBCXX_DEBUG_VERIFY(__pos <= this->size(),
353			      _M_message(__gnu_debug::__msg_subscript_oob)
354			      ._M_sequence(*this, "this")
355			      ._M_integer(__pos, "__pos")
356			      ._M_integer(this->size(), "size"));
357#endif
358	return _M_base()[__pos];
359      }
360
361      using _Base::at;
362
363#if __cplusplus >= 201103L
364      using _Base::front;
365      using _Base::back;
366#endif
367
368      // 21.3.5 modifiers:
369      basic_string&
370      operator+=(const basic_string& __str)
371      {
372	_M_base() += __str;
373	this->_M_invalidate_all();
374	return *this;
375      }
376
377      basic_string&
378      operator+=(const _CharT* __s)
379      {
380	__glibcxx_check_string(__s);
381	_M_base() += __s;
382	this->_M_invalidate_all();
383	return *this;
384      }
385
386      basic_string&
387      operator+=(_CharT __c)
388      {
389	_M_base() += __c;
390	this->_M_invalidate_all();
391	return *this;
392      }
393
394#if __cplusplus >= 201103L
395      basic_string&
396      operator+=(std::initializer_list<_CharT> __l)
397      {
398	_M_base() += __l;
399	this->_M_invalidate_all();
400	return *this;
401      }
402#endif // C++11
403
404      basic_string&
405      append(const basic_string& __str)
406      {
407	_Base::append(__str);
408	this->_M_invalidate_all();
409	return *this;
410      }
411
412      basic_string&
413      append(const basic_string& __str, size_type __pos, size_type __n)
414      {
415	_Base::append(__str, __pos, __n);
416	this->_M_invalidate_all();
417	return *this;
418      }
419
420      basic_string&
421      append(const _CharT* __s, size_type __n)
422      {
423	__glibcxx_check_string_len(__s, __n);
424	_Base::append(__s, __n);
425	this->_M_invalidate_all();
426	return *this;
427      }
428
429      basic_string&
430      append(const _CharT* __s)
431      {
432	__glibcxx_check_string(__s);
433	_Base::append(__s);
434	this->_M_invalidate_all();
435	return *this;
436      }
437
438      basic_string&
439      append(size_type __n, _CharT __c)
440      {
441	_Base::append(__n, __c);
442	this->_M_invalidate_all();
443	return *this;
444      }
445
446      template<typename _InputIterator>
447	basic_string&
448	append(_InputIterator __first, _InputIterator __last)
449	{
450	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
451	  __glibcxx_check_valid_range2(__first, __last, __dist);
452
453	  if (__dist.second >= __dp_sign)
454	    _Base::append(__gnu_debug::__unsafe(__first),
455			  __gnu_debug::__unsafe(__last));
456	  else
457	    _Base::append(__first, __last);
458
459	  this->_M_invalidate_all();
460	  return *this;
461	}
462
463      // _GLIBCXX_RESOLVE_LIB_DEFECTS
464      // 7. string clause minor problems
465      void
466      push_back(_CharT __c)
467      {
468	_Base::push_back(__c);
469	this->_M_invalidate_all();
470      }
471
472      basic_string&
473      assign(const basic_string& __x)
474      {
475	_Base::assign(__x);
476	this->_M_invalidate_all();
477	return *this;
478      }
479
480#if __cplusplus >= 201103L
481      basic_string&
482      assign(basic_string&& __x)
483      noexcept(noexcept(std::declval<_Base&>().assign(std::move(__x))))
484      {
485	_Base::assign(std::move(__x));
486	this->_M_invalidate_all();
487	return *this;
488      }
489#endif // C++11
490
491      basic_string&
492      assign(const basic_string& __str, size_type __pos, size_type __n)
493      {
494	_Base::assign(__str, __pos, __n);
495	this->_M_invalidate_all();
496	return *this;
497      }
498
499      basic_string&
500      assign(const _CharT* __s, size_type __n)
501      {
502	__glibcxx_check_string_len(__s, __n);
503	_Base::assign(__s, __n);
504	this->_M_invalidate_all();
505	return *this;
506      }
507
508      basic_string&
509      assign(const _CharT* __s)
510      {
511	__glibcxx_check_string(__s);
512	_Base::assign(__s);
513	this->_M_invalidate_all();
514	return *this;
515      }
516
517      basic_string&
518      assign(size_type __n, _CharT __c)
519      {
520	_Base::assign(__n, __c);
521	this->_M_invalidate_all();
522	return *this;
523      }
524
525      template<typename _InputIterator>
526	basic_string&
527	assign(_InputIterator __first, _InputIterator __last)
528	{
529	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
530	  __glibcxx_check_valid_range2(__first, __last, __dist);
531
532	  if (__dist.second >= __dp_sign)
533	    _Base::assign(__gnu_debug::__unsafe(__first),
534			  __gnu_debug::__unsafe(__last));
535	  else
536	    _Base::assign(__first, __last);
537
538	  this->_M_invalidate_all();
539	  return *this;
540	}
541
542#if __cplusplus >= 201103L
543      basic_string&
544      assign(std::initializer_list<_CharT> __l)
545      {
546	_Base::assign(__l);
547	this->_M_invalidate_all();
548	return *this;
549      }
550#endif // C++11
551
552      basic_string&
553      insert(size_type __pos1, const basic_string& __str)
554      {
555	_Base::insert(__pos1, __str);
556	this->_M_invalidate_all();
557	return *this;
558      }
559
560      basic_string&
561      insert(size_type __pos1, const basic_string& __str,
562	     size_type __pos2, size_type __n)
563      {
564	_Base::insert(__pos1, __str, __pos2, __n);
565	this->_M_invalidate_all();
566	return *this;
567      }
568
569      basic_string&
570      insert(size_type __pos, const _CharT* __s, size_type __n)
571      {
572	__glibcxx_check_string(__s);
573	_Base::insert(__pos, __s, __n);
574	this->_M_invalidate_all();
575	return *this;
576      }
577
578      basic_string&
579      insert(size_type __pos, const _CharT* __s)
580      {
581	__glibcxx_check_string(__s);
582	_Base::insert(__pos, __s);
583	this->_M_invalidate_all();
584	return *this;
585      }
586
587      basic_string&
588      insert(size_type __pos, size_type __n, _CharT __c)
589      {
590	_Base::insert(__pos, __n, __c);
591	this->_M_invalidate_all();
592	return *this;
593      }
594
595      iterator
596      insert(__const_iterator __p, _CharT __c)
597      {
598	__glibcxx_check_insert(__p);
599	typename _Base::iterator __res = _Base::insert(__p.base(), __c);
600	this->_M_invalidate_all();
601	return iterator(__res, this);
602      }
603
604#if __cplusplus >= 201103L
605      iterator
606      insert(const_iterator __p, size_type __n, _CharT __c)
607      {
608	__glibcxx_check_insert(__p);
609#if _GLIBCXX_USE_CXX11_ABI
610	typename _Base::iterator __res = _Base::insert(__p.base(), __n, __c);
611#else
612	const size_type __offset = __p.base() - _Base::cbegin();
613	_Base::insert(_Base::begin() + __offset, __n, __c);
614	typename _Base::iterator __res = _Base::begin() + __offset;
615#endif
616	this->_M_invalidate_all();
617	return iterator(__res, this);
618      }
619#else
620      void
621      insert(iterator __p, size_type __n, _CharT __c)
622      {
623	__glibcxx_check_insert(__p);
624	_Base::insert(__p.base(), __n, __c);
625	this->_M_invalidate_all();
626      }
627#endif
628
629      template<typename _InputIterator>
630	iterator
631	insert(__const_iterator __p,
632	       _InputIterator __first, _InputIterator __last)
633	{
634	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
635	  __glibcxx_check_insert_range(__p, __first, __last, __dist);
636
637	  typename _Base::iterator __res;
638#if _GLIBCXX_USE_CXX11_ABI && __cplusplus >= 201103
639	  if (__dist.second >= __dp_sign)
640	    __res = _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
641				  __gnu_debug::__unsafe(__last));
642	  else
643	    __res = _Base::insert(__p.base(), __first, __last);
644#else
645	  const size_type __offset = __p.base() - _Base::begin();
646	  _Base::insert(__p.base(), __first, __last);
647	  __res = _Base::begin() + __offset;
648#endif
649	  this->_M_invalidate_all();
650	  return iterator(__res, this);
651	}
652
653#if __cplusplus >= 201103L
654      iterator
655      insert(const_iterator __p, std::initializer_list<_CharT> __l)
656      {
657	__glibcxx_check_insert(__p);
658#if _GLIBCXX_USE_CXX11_ABI
659	const auto __res = _Base::insert(__p.base(), __l);
660#else
661	const size_type __offset = __p.base() - _Base::cbegin();
662	_Base::insert(_Base::begin() + __offset, __l);
663	auto __res = _Base::begin() + __offset;
664#endif
665	this->_M_invalidate_all();
666	return iterator(__res, this);
667      }
668#endif // C++11
669
670      basic_string&
671      erase(size_type __pos = 0, size_type __n = _Base::npos)
672      {
673	_Base::erase(__pos, __n);
674	this->_M_invalidate_all();
675	return *this;
676      }
677
678      iterator
679      erase(iterator __position)
680      {
681	__glibcxx_check_erase(__position);
682	typename _Base::iterator __res = _Base::erase(__position.base());
683	this->_M_invalidate_all();
684	return iterator(__res, this);
685      }
686
687      iterator
688      erase(iterator __first, iterator __last)
689      {
690	// _GLIBCXX_RESOLVE_LIB_DEFECTS
691	// 151. can't currently clear() empty container
692	__glibcxx_check_erase_range(__first, __last);
693	typename _Base::iterator __res = _Base::erase(__first.base(),
694						      __last.base());
695	this->_M_invalidate_all();
696	return iterator(__res, this);
697      }
698
699#if __cplusplus >= 201103L
700      void
701      pop_back() // noexcept
702      {
703	__glibcxx_check_nonempty();
704	_Base::pop_back();
705	this->_M_invalidate_all();
706      }
707#endif // C++11
708
709      basic_string&
710      replace(size_type __pos1, size_type __n1, const basic_string& __str)
711      {
712	_Base::replace(__pos1, __n1, __str);
713	this->_M_invalidate_all();
714	return *this;
715      }
716
717      basic_string&
718      replace(size_type __pos1, size_type __n1, const basic_string& __str,
719	      size_type __pos2, size_type __n2)
720      {
721	_Base::replace(__pos1, __n1, __str, __pos2, __n2);
722	this->_M_invalidate_all();
723	return *this;
724      }
725
726      basic_string&
727      replace(size_type __pos, size_type __n1, const _CharT* __s,
728	      size_type __n2)
729      {
730	__glibcxx_check_string_len(__s, __n2);
731	_Base::replace(__pos, __n1, __s, __n2);
732	this->_M_invalidate_all();
733	return *this;
734      }
735
736      basic_string&
737      replace(size_type __pos, size_type __n1, const _CharT* __s)
738      {
739	__glibcxx_check_string(__s);
740	_Base::replace(__pos, __n1, __s);
741	this->_M_invalidate_all();
742	return *this;
743      }
744
745      basic_string&
746      replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
747      {
748	_Base::replace(__pos, __n1, __n2, __c);
749	this->_M_invalidate_all();
750	return *this;
751      }
752
753      basic_string&
754      replace(__const_iterator __i1, __const_iterator __i2,
755	      const basic_string& __str)
756      {
757	__glibcxx_check_erase_range(__i1, __i2);
758	_Base::replace(__i1.base(), __i2.base(), __str);
759	this->_M_invalidate_all();
760	return *this;
761      }
762
763      basic_string&
764      replace(__const_iterator __i1, __const_iterator __i2,
765	      const _CharT* __s, size_type __n)
766      {
767	__glibcxx_check_erase_range(__i1, __i2);
768	__glibcxx_check_string_len(__s, __n);
769	_Base::replace(__i1.base(), __i2.base(), __s, __n);
770	this->_M_invalidate_all();
771	return *this;
772      }
773
774      basic_string&
775      replace(__const_iterator __i1, __const_iterator __i2,
776	      const _CharT* __s)
777      {
778	__glibcxx_check_erase_range(__i1, __i2);
779	__glibcxx_check_string(__s);
780	_Base::replace(__i1.base(), __i2.base(), __s);
781	this->_M_invalidate_all();
782	return *this;
783      }
784
785      basic_string&
786      replace(__const_iterator __i1, __const_iterator __i2,
787	      size_type __n, _CharT __c)
788      {
789	__glibcxx_check_erase_range(__i1, __i2);
790	_Base::replace(__i1.base(), __i2.base(), __n, __c);
791	this->_M_invalidate_all();
792	return *this;
793      }
794
795      template<typename _InputIterator>
796	basic_string&
797	replace(__const_iterator __i1, __const_iterator __i2,
798		_InputIterator __j1, _InputIterator __j2)
799	{
800	  __glibcxx_check_erase_range(__i1, __i2);
801
802	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
803	  __glibcxx_check_valid_range2(__j1, __j2, __dist);
804
805	  if (__dist.second >= __dp_sign)
806	    _Base::replace(__i1.base(), __i2.base(),
807			   __gnu_debug::__unsafe(__j1),
808			   __gnu_debug::__unsafe(__j2));
809	  else
810	    _Base::replace(__i1.base(), __i2.base(), __j1, __j2);
811
812	  this->_M_invalidate_all();
813	  return *this;
814	}
815
816#if __cplusplus >= 201103L
817      basic_string&
818      replace(__const_iterator __i1, __const_iterator __i2,
819	      std::initializer_list<_CharT> __l)
820      {
821	__glibcxx_check_erase_range(__i1, __i2);
822	_Base::replace(__i1.base(), __i2.base(), __l);
823	this->_M_invalidate_all();
824	return *this;
825      }
826#endif // C++11
827
828      size_type
829      copy(_CharT* __s, size_type __n, size_type __pos = 0) const
830      {
831	__glibcxx_check_string_len(__s, __n);
832	return _Base::copy(__s, __n, __pos);
833      }
834
835      void
836      swap(basic_string& __x)
837	_GLIBCXX_NOEXCEPT_IF(std::__is_nothrow_swappable<_Base>::value)
838      {
839	_Safe::_M_swap(__x);
840	_Base::swap(__x);
841      }
842
843      // 21.3.6 string operations:
844      const _CharT*
845      c_str() const _GLIBCXX_NOEXCEPT
846      {
847	const _CharT* __res = _Base::c_str();
848	this->_M_invalidate_all();
849	return __res;
850      }
851
852      const _CharT*
853      data() const _GLIBCXX_NOEXCEPT
854      {
855	const _CharT* __res = _Base::data();
856	this->_M_invalidate_all();
857	return __res;
858      }
859
860      using _Base::get_allocator;
861
862      size_type
863      find(const basic_string& __str, size_type __pos = 0) const
864	_GLIBCXX_NOEXCEPT
865      { return _Base::find(__str, __pos); }
866
867      size_type
868      find(const _CharT* __s, size_type __pos, size_type __n) const
869      {
870	__glibcxx_check_string(__s);
871	return _Base::find(__s, __pos, __n);
872      }
873
874      size_type
875      find(const _CharT* __s, size_type __pos = 0) const
876      {
877	__glibcxx_check_string(__s);
878	return _Base::find(__s, __pos);
879      }
880
881      size_type
882      find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
883      { return _Base::find(__c, __pos); }
884
885      size_type
886      rfind(const basic_string& __str, size_type __pos = _Base::npos) const
887	_GLIBCXX_NOEXCEPT
888      { return _Base::rfind(__str, __pos); }
889
890      size_type
891      rfind(const _CharT* __s, size_type __pos, size_type __n) const
892      {
893	__glibcxx_check_string_len(__s, __n);
894	return _Base::rfind(__s, __pos, __n);
895      }
896
897      size_type
898      rfind(const _CharT* __s, size_type __pos = _Base::npos) const
899      {
900	__glibcxx_check_string(__s);
901	return _Base::rfind(__s, __pos);
902      }
903
904      size_type
905      rfind(_CharT __c, size_type __pos = _Base::npos) const _GLIBCXX_NOEXCEPT
906      { return _Base::rfind(__c, __pos); }
907
908      size_type
909      find_first_of(const basic_string& __str, size_type __pos = 0) const
910	_GLIBCXX_NOEXCEPT
911      { return _Base::find_first_of(__str, __pos); }
912
913      size_type
914      find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
915      {
916	__glibcxx_check_string(__s);
917	return _Base::find_first_of(__s, __pos, __n);
918      }
919
920      size_type
921      find_first_of(const _CharT* __s, size_type __pos = 0) const
922      {
923	__glibcxx_check_string(__s);
924	return _Base::find_first_of(__s, __pos);
925      }
926
927      size_type
928      find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
929      { return _Base::find_first_of(__c, __pos); }
930
931      size_type
932      find_last_of(const basic_string& __str,
933		   size_type __pos = _Base::npos) const _GLIBCXX_NOEXCEPT
934      { return _Base::find_last_of(__str, __pos); }
935
936      size_type
937      find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
938      {
939	__glibcxx_check_string(__s);
940	return _Base::find_last_of(__s, __pos, __n);
941      }
942
943      size_type
944      find_last_of(const _CharT* __s, size_type __pos = _Base::npos) const
945      {
946	__glibcxx_check_string(__s);
947	return _Base::find_last_of(__s, __pos);
948      }
949
950      size_type
951      find_last_of(_CharT __c, size_type __pos = _Base::npos) const
952	_GLIBCXX_NOEXCEPT
953      { return _Base::find_last_of(__c, __pos); }
954
955      size_type
956      find_first_not_of(const basic_string& __str, size_type __pos = 0) const
957	_GLIBCXX_NOEXCEPT
958      { return _Base::find_first_not_of(__str, __pos); }
959
960      size_type
961      find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
962      {
963	__glibcxx_check_string_len(__s, __n);
964	return _Base::find_first_not_of(__s, __pos, __n);
965      }
966
967      size_type
968      find_first_not_of(const _CharT* __s, size_type __pos = 0) const
969      {
970	__glibcxx_check_string(__s);
971	return _Base::find_first_not_of(__s, __pos);
972      }
973
974      size_type
975      find_first_not_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
976      { return _Base::find_first_not_of(__c, __pos); }
977
978      size_type
979      find_last_not_of(const basic_string& __str,
980		       size_type __pos = _Base::npos) const
981	_GLIBCXX_NOEXCEPT
982      { return _Base::find_last_not_of(__str, __pos); }
983
984      size_type
985      find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
986      {
987	__glibcxx_check_string(__s);
988	return _Base::find_last_not_of(__s, __pos, __n);
989      }
990
991      size_type
992      find_last_not_of(const _CharT* __s, size_type __pos = _Base::npos) const
993      {
994	__glibcxx_check_string(__s);
995	return _Base::find_last_not_of(__s, __pos);
996      }
997
998      size_type
999      find_last_not_of(_CharT __c, size_type __pos = _Base::npos) const
1000	_GLIBCXX_NOEXCEPT
1001      { return _Base::find_last_not_of(__c, __pos); }
1002
1003      basic_string
1004      substr(size_type __pos = 0, size_type __n = _Base::npos) const
1005      { return basic_string(_Base::substr(__pos, __n)); }
1006
1007      int
1008      compare(const basic_string& __str) const
1009      { return _Base::compare(__str); }
1010
1011      int
1012      compare(size_type __pos1, size_type __n1,
1013	      const basic_string& __str) const
1014      { return _Base::compare(__pos1, __n1, __str); }
1015
1016      int
1017      compare(size_type __pos1, size_type __n1, const basic_string& __str,
1018	      size_type __pos2, size_type __n2) const
1019      { return _Base::compare(__pos1, __n1, __str, __pos2, __n2); }
1020
1021      int
1022      compare(const _CharT* __s) const
1023      {
1024	__glibcxx_check_string(__s);
1025	return _Base::compare(__s);
1026      }
1027
1028      //  _GLIBCXX_RESOLVE_LIB_DEFECTS
1029      //  5. string::compare specification questionable
1030      int
1031      compare(size_type __pos1, size_type __n1, const _CharT* __s) const
1032      {
1033	__glibcxx_check_string(__s);
1034	return _Base::compare(__pos1, __n1, __s);
1035      }
1036
1037      //  _GLIBCXX_RESOLVE_LIB_DEFECTS
1038      //  5. string::compare specification questionable
1039      int
1040      compare(size_type __pos1, size_type __n1,const _CharT* __s,
1041	      size_type __n2) const
1042      {
1043	__glibcxx_check_string_len(__s, __n2);
1044	return _Base::compare(__pos1, __n1, __s, __n2);
1045      }
1046
1047      _Base&
1048      _M_base() _GLIBCXX_NOEXCEPT		{ return *this; }
1049
1050      const _Base&
1051      _M_base() const _GLIBCXX_NOEXCEPT	{ return *this; }
1052
1053      using _Safe::_M_invalidate_all;
1054    };
1055
1056  template<typename _CharT, typename _Traits, typename _Allocator>
1057    inline basic_string<_CharT,_Traits,_Allocator>
1058    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1059	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1060    { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; }
1061
1062  template<typename _CharT, typename _Traits, typename _Allocator>
1063    inline basic_string<_CharT,_Traits,_Allocator>
1064    operator+(const _CharT* __lhs,
1065	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1066    {
1067      __glibcxx_check_string(__lhs);
1068      return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs;
1069    }
1070
1071  template<typename _CharT, typename _Traits, typename _Allocator>
1072    inline basic_string<_CharT,_Traits,_Allocator>
1073    operator+(_CharT __lhs,
1074	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1075    { return basic_string<_CharT,_Traits,_Allocator>(1, __lhs) += __rhs; }
1076
1077  template<typename _CharT, typename _Traits, typename _Allocator>
1078    inline basic_string<_CharT,_Traits,_Allocator>
1079    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1080	      const _CharT* __rhs)
1081    {
1082      __glibcxx_check_string(__rhs);
1083      return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs;
1084    }
1085
1086  template<typename _CharT, typename _Traits, typename _Allocator>
1087    inline basic_string<_CharT,_Traits,_Allocator>
1088    operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1089	      _CharT __rhs)
1090    { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; }
1091
1092  template<typename _CharT, typename _Traits, typename _Allocator>
1093    inline bool
1094    operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1095	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1096    { return __lhs._M_base() == __rhs._M_base(); }
1097
1098  template<typename _CharT, typename _Traits, typename _Allocator>
1099    inline bool
1100    operator==(const _CharT* __lhs,
1101	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1102    {
1103      __glibcxx_check_string(__lhs);
1104      return __lhs == __rhs._M_base();
1105    }
1106
1107  template<typename _CharT, typename _Traits, typename _Allocator>
1108    inline bool
1109    operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1110	       const _CharT* __rhs)
1111    {
1112      __glibcxx_check_string(__rhs);
1113      return __lhs._M_base() == __rhs;
1114    }
1115
1116  template<typename _CharT, typename _Traits, typename _Allocator>
1117    inline bool
1118    operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1119	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1120    { return __lhs._M_base() != __rhs._M_base(); }
1121
1122  template<typename _CharT, typename _Traits, typename _Allocator>
1123    inline bool
1124    operator!=(const _CharT* __lhs,
1125	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1126    {
1127      __glibcxx_check_string(__lhs);
1128      return __lhs != __rhs._M_base();
1129    }
1130
1131  template<typename _CharT, typename _Traits, typename _Allocator>
1132    inline bool
1133    operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1134	       const _CharT* __rhs)
1135    {
1136      __glibcxx_check_string(__rhs);
1137      return __lhs._M_base() != __rhs;
1138    }
1139
1140  template<typename _CharT, typename _Traits, typename _Allocator>
1141    inline bool
1142    operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1143	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1144    { return __lhs._M_base() < __rhs._M_base(); }
1145
1146  template<typename _CharT, typename _Traits, typename _Allocator>
1147    inline bool
1148    operator<(const _CharT* __lhs,
1149	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1150    {
1151      __glibcxx_check_string(__lhs);
1152      return __lhs < __rhs._M_base();
1153    }
1154
1155  template<typename _CharT, typename _Traits, typename _Allocator>
1156    inline bool
1157    operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1158	      const _CharT* __rhs)
1159    {
1160      __glibcxx_check_string(__rhs);
1161      return __lhs._M_base() < __rhs;
1162    }
1163
1164  template<typename _CharT, typename _Traits, typename _Allocator>
1165    inline bool
1166    operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1167	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1168    { return __lhs._M_base() <= __rhs._M_base(); }
1169
1170  template<typename _CharT, typename _Traits, typename _Allocator>
1171    inline bool
1172    operator<=(const _CharT* __lhs,
1173	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1174    {
1175      __glibcxx_check_string(__lhs);
1176      return __lhs <= __rhs._M_base();
1177    }
1178
1179  template<typename _CharT, typename _Traits, typename _Allocator>
1180    inline bool
1181    operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1182	       const _CharT* __rhs)
1183    {
1184      __glibcxx_check_string(__rhs);
1185      return __lhs._M_base() <= __rhs;
1186    }
1187
1188  template<typename _CharT, typename _Traits, typename _Allocator>
1189    inline bool
1190    operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1191	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1192    { return __lhs._M_base() >= __rhs._M_base(); }
1193
1194  template<typename _CharT, typename _Traits, typename _Allocator>
1195    inline bool
1196    operator>=(const _CharT* __lhs,
1197	       const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1198    {
1199      __glibcxx_check_string(__lhs);
1200      return __lhs >= __rhs._M_base();
1201    }
1202
1203  template<typename _CharT, typename _Traits, typename _Allocator>
1204    inline bool
1205    operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1206	       const _CharT* __rhs)
1207    {
1208      __glibcxx_check_string(__rhs);
1209      return __lhs._M_base() >= __rhs;
1210    }
1211
1212  template<typename _CharT, typename _Traits, typename _Allocator>
1213    inline bool
1214    operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1215	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1216    { return __lhs._M_base() > __rhs._M_base(); }
1217
1218  template<typename _CharT, typename _Traits, typename _Allocator>
1219    inline bool
1220    operator>(const _CharT* __lhs,
1221	      const basic_string<_CharT,_Traits,_Allocator>& __rhs)
1222    {
1223      __glibcxx_check_string(__lhs);
1224      return __lhs > __rhs._M_base();
1225    }
1226
1227  template<typename _CharT, typename _Traits, typename _Allocator>
1228    inline bool
1229    operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
1230	      const _CharT* __rhs)
1231    {
1232      __glibcxx_check_string(__rhs);
1233      return __lhs._M_base() > __rhs;
1234    }
1235
1236  // 21.3.7.8:
1237  template<typename _CharT, typename _Traits, typename _Allocator>
1238    inline void
1239    swap(basic_string<_CharT,_Traits,_Allocator>& __lhs,
1240	 basic_string<_CharT,_Traits,_Allocator>& __rhs)
1241    { __lhs.swap(__rhs); }
1242
1243  template<typename _CharT, typename _Traits, typename _Allocator>
1244    std::basic_ostream<_CharT, _Traits>&
1245    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
1246	       const basic_string<_CharT, _Traits, _Allocator>& __str)
1247    { return __os << __str._M_base(); }
1248
1249  template<typename _CharT, typename _Traits, typename _Allocator>
1250    std::basic_istream<_CharT,_Traits>&
1251    operator>>(std::basic_istream<_CharT,_Traits>& __is,
1252	       basic_string<_CharT,_Traits,_Allocator>& __str)
1253    {
1254      std::basic_istream<_CharT,_Traits>& __res = __is >> __str._M_base();
1255      __str._M_invalidate_all();
1256      return __res;
1257    }
1258
1259  template<typename _CharT, typename _Traits, typename _Allocator>
1260    std::basic_istream<_CharT,_Traits>&
1261    getline(std::basic_istream<_CharT,_Traits>& __is,
1262	    basic_string<_CharT,_Traits,_Allocator>& __str, _CharT __delim)
1263    {
1264      std::basic_istream<_CharT,_Traits>& __res = getline(__is,
1265							  __str._M_base(),
1266							__delim);
1267      __str._M_invalidate_all();
1268      return __res;
1269    }
1270
1271  template<typename _CharT, typename _Traits, typename _Allocator>
1272    std::basic_istream<_CharT,_Traits>&
1273    getline(std::basic_istream<_CharT,_Traits>& __is,
1274	    basic_string<_CharT,_Traits,_Allocator>& __str)
1275    {
1276      std::basic_istream<_CharT,_Traits>& __res = getline(__is,
1277							  __str._M_base());
1278      __str._M_invalidate_all();
1279      return __res;
1280    }
1281
1282  typedef basic_string<char>    string;
1283
1284#ifdef _GLIBCXX_USE_WCHAR_T
1285  typedef basic_string<wchar_t> wstring;
1286#endif
1287
1288  template<typename _CharT, typename _Traits, typename _Allocator>
1289    struct _Insert_range_from_self_is_safe<
1290      __gnu_debug::basic_string<_CharT, _Traits, _Allocator> >
1291      { enum { __value = 1 }; };
1292
1293} // namespace __gnu_debug
1294
1295#endif
1296