1// Debug-mode error formatting implementation -*- C++ -*-
2
3// Copyright (C) 2003-2022 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/formatter.h
26 *  This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_FORMATTER_H
30#define _GLIBCXX_DEBUG_FORMATTER_H 1
31
32#include <bits/c++config.h>
33
34#if __cpp_rtti
35# include <typeinfo>
36# define _GLIBCXX_TYPEID(_Type) &typeid(_Type)
37#else
38namespace std
39{
40  class type_info;
41}
42# define _GLIBCXX_TYPEID(_Type) 0
43#endif
44
45#if __cplusplus >= 201103L
46namespace __gnu_cxx
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50template<typename _Iterator, typename _Container>
51  class __normal_iterator;
52
53_GLIBCXX_END_NAMESPACE_VERSION
54}
55
56namespace std
57{
58_GLIBCXX_BEGIN_NAMESPACE_VERSION
59
60template<typename _Iterator>
61  class reverse_iterator;
62
63template<typename _Iterator>
64  class move_iterator;
65
66_GLIBCXX_END_NAMESPACE_VERSION
67}
68#endif
69
70namespace __gnu_debug
71{
72  using std::type_info;
73
74  template<typename _Iterator>
75    _GLIBCXX_CONSTEXPR
76    bool __check_singular(_Iterator const&);
77
78  class _Safe_sequence_base;
79
80  template<typename _Iterator, typename _Sequence, typename _Category>
81    class _Safe_iterator;
82
83  template<typename _Iterator, typename _Sequence>
84    class _Safe_local_iterator;
85
86  template<typename _Sequence>
87    class _Safe_sequence;
88
89  enum _Debug_msg_id
90  {
91    // General checks
92    __msg_valid_range,
93    __msg_insert_singular,
94    __msg_insert_different,
95    __msg_erase_bad,
96    __msg_erase_different,
97    __msg_subscript_oob,
98    __msg_empty,
99    __msg_unpartitioned,
100    __msg_unpartitioned_pred,
101    __msg_unsorted,
102    __msg_unsorted_pred,
103    __msg_not_heap,
104    __msg_not_heap_pred,
105    // std::bitset checks
106    __msg_bad_bitset_write,
107    __msg_bad_bitset_read,
108    __msg_bad_bitset_flip,
109    // std::list checks
110    __msg_self_splice,
111    __msg_splice_alloc,
112    __msg_splice_bad,
113    __msg_splice_other,
114    __msg_splice_overlap,
115    // iterator checks
116    __msg_init_singular,
117    __msg_init_copy_singular,
118    __msg_init_const_singular,
119    __msg_copy_singular,
120    __msg_bad_deref,
121    __msg_bad_inc,
122    __msg_bad_dec,
123    __msg_iter_subscript_oob,
124    __msg_advance_oob,
125    __msg_retreat_oob,
126    __msg_iter_compare_bad,
127    __msg_compare_different,
128    __msg_iter_order_bad,
129    __msg_order_different,
130    __msg_distance_bad,
131    __msg_distance_different,
132    // istream_iterator
133    __msg_deref_istream,
134    __msg_inc_istream,
135    // ostream_iterator
136    __msg_output_ostream,
137    // istreambuf_iterator
138    __msg_deref_istreambuf,
139    __msg_inc_istreambuf,
140    // forward_list
141    __msg_insert_after_end,
142    __msg_erase_after_bad,
143    __msg_valid_range2,
144    // unordered container local iterators
145    __msg_local_iter_compare_bad,
146    __msg_non_empty_range,
147    // self move assign (no longer used)
148    __msg_self_move_assign,
149    // unordered container buckets
150    __msg_bucket_index_oob,
151    __msg_valid_load_factor,
152    // others
153    __msg_equal_allocs,
154    __msg_insert_range_from_self,
155    __msg_irreflexive_ordering
156  };
157
158  class _Error_formatter
159  {
160    // Tags denoting the type of parameter for construction
161    struct _Is_iterator { };
162    struct _Is_iterator_value_type { };
163    struct _Is_sequence { };
164    struct _Is_instance { };
165
166  public:
167    /// Whether an iterator is constant, mutable, or unknown
168    enum _Constness
169    {
170      __unknown_constness,
171      __const_iterator,
172      __mutable_iterator,
173      __last_constness
174    };
175
176    // The state of the iterator (fine-grained), if we know it.
177    enum _Iterator_state
178    {
179      __unknown_state,
180      __singular,	// singular, may still be attached to a sequence
181      __begin,		// dereferenceable, and at the beginning
182      __middle,		// dereferenceable, not at the beginning
183      __end,		// past-the-end, may be at beginning if sequence empty
184      __before_begin,	// before begin
185      __rbegin,		// dereferenceable, and at the reverse-beginning
186      __rmiddle,	// reverse-dereferenceable, not at the reverse-beginning
187      __rend,		// reverse-past-the-end
188      __last_state
189    };
190
191    // A parameter that may be referenced by an error message
192    struct _Parameter
193    {
194      enum
195      {
196	__unused_param,
197	__iterator,
198	__sequence,
199	__integer,
200	__string,
201	__instance,
202	__iterator_value_type
203      } _M_kind;
204
205      struct _Named
206      {
207	const char*		_M_name;
208      };
209
210      struct _Type : _Named
211      {
212	const type_info*	_M_type;
213      };
214
215      struct _Instance : _Type
216      {
217	const void*		_M_address;
218      };
219
220      union
221      {
222	// When _M_kind == __iterator
223	struct : _Instance
224	{
225	  _Constness		_M_constness;
226	  _Iterator_state	_M_state;
227	  const void*		_M_sequence;
228	  const type_info*	_M_seq_type;
229	} _M_iterator;
230
231	// When _M_kind == __sequence
232	_Instance _M_sequence;
233
234	// When _M_kind == __integer
235	struct : _Named
236	{
237	  long			_M_value;
238	} _M_integer;
239
240	// When _M_kind == __string
241	struct : _Named
242	{
243	  const char*		_M_value;
244	} _M_string;
245
246	// When _M_kind == __instance
247	_Instance _M_instance;
248
249	// When _M_kind == __iterator_value_type
250	_Type _M_iterator_value_type;
251      } _M_variant;
252
253      _Parameter() : _M_kind(__unused_param), _M_variant() { }
254
255      _Parameter(long __value, const char* __name)
256      : _M_kind(__integer), _M_variant()
257      {
258	_M_variant._M_integer._M_name = __name;
259	_M_variant._M_integer._M_value = __value;
260      }
261
262      _Parameter(const char* __value, const char* __name)
263      : _M_kind(__string), _M_variant()
264      {
265	_M_variant._M_string._M_name = __name;
266	_M_variant._M_string._M_value = __value;
267      }
268
269      template<typename _Iterator, typename _Sequence, typename _Category>
270	_Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it,
271		   const char* __name, _Is_iterator)
272	: _M_kind(__iterator),  _M_variant()
273	{
274	  _M_variant._M_iterator._M_name = __name;
275	  _M_variant._M_iterator._M_address = std::__addressof(__it);
276	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
277	  _M_variant._M_iterator._M_constness =
278	    __it._S_constant() ? __const_iterator : __mutable_iterator;
279	  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
280	  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
281
282	  if (__it._M_singular())
283	    _M_variant._M_iterator._M_state = __singular;
284	  else
285	    {
286	      if (__it._M_is_before_begin())
287		_M_variant._M_iterator._M_state = __before_begin;
288	      else if (__it._M_is_end())
289		_M_variant._M_iterator._M_state = __end;
290	      else if (__it._M_is_begin())
291		_M_variant._M_iterator._M_state = __begin;
292	      else
293		_M_variant._M_iterator._M_state = __middle;
294	    }
295	}
296
297      template<typename _Iterator, typename _Sequence>
298	_Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
299		   const char* __name, _Is_iterator)
300	: _M_kind(__iterator),  _M_variant()
301	{
302	  _M_variant._M_iterator._M_name = __name;
303	  _M_variant._M_iterator._M_address = std::__addressof(__it);
304	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
305	  _M_variant._M_iterator._M_constness =
306	    __it._S_constant() ? __const_iterator : __mutable_iterator;
307	  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
308	  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
309
310	  if (__it._M_singular())
311	    _M_variant._M_iterator._M_state = __singular;
312	  else
313	    {
314	      if (__it._M_is_end())
315		_M_variant._M_iterator._M_state = __end;
316	      else if (__it._M_is_begin())
317		_M_variant._M_iterator._M_state = __begin;
318	      else
319		_M_variant._M_iterator._M_state = __middle;
320	    }
321	}
322
323      template<typename _Type>
324	_Parameter(const _Type* const& __it, const char* __name, _Is_iterator)
325	: _M_kind(__iterator), _M_variant()
326	{
327	  _M_variant._M_iterator._M_name = __name;
328	  _M_variant._M_iterator._M_address = std::__addressof(__it);
329	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
330	  _M_variant._M_iterator._M_constness = __const_iterator;
331	  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
332	  _M_variant._M_iterator._M_sequence = 0;
333	  _M_variant._M_iterator._M_seq_type = 0;
334	}
335
336      template<typename _Type>
337	_Parameter(_Type* const& __it, const char* __name, _Is_iterator)
338	: _M_kind(__iterator), _M_variant()
339	{
340	  _M_variant._M_iterator._M_name = __name;
341	  _M_variant._M_iterator._M_address = std::__addressof(__it);
342	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
343	  _M_variant._M_iterator._M_constness = __mutable_iterator;
344	  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
345	  _M_variant._M_iterator._M_sequence = 0;
346	  _M_variant._M_iterator._M_seq_type = 0;
347	}
348
349      template<typename _Iterator>
350	_Parameter(_Iterator const& __it, const char* __name, _Is_iterator)
351	: _M_kind(__iterator), _M_variant()
352	{
353	  _M_variant._M_iterator._M_name = __name;
354	  _M_variant._M_iterator._M_address = std::__addressof(__it);
355	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
356	  _M_variant._M_iterator._M_constness = __unknown_constness;
357	  _M_variant._M_iterator._M_state =
358	    __gnu_debug::__check_singular(__it) ? __singular : __unknown_state;
359	  _M_variant._M_iterator._M_sequence = 0;
360	  _M_variant._M_iterator._M_seq_type = 0;
361	}
362
363#if __cplusplus >= 201103L
364      // The following constructors are only defined in C++11 to take
365      // advantage of the constructor delegation feature.
366      template<typename _Iterator, typename _Container>
367        _Parameter(
368	  __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it,
369	const char* __name, _Is_iterator)
370	: _Parameter(__it.base(), __name, _Is_iterator{})
371	{ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
372
373      template<typename _Iterator>
374	_Parameter(std::reverse_iterator<_Iterator> const& __it,
375		   const char* __name, _Is_iterator)
376	: _Parameter(__it.base(), __name, _Is_iterator{})
377	{
378	  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
379	  _M_variant._M_iterator._M_state
380	    = _S_reverse_state(_M_variant._M_iterator._M_state);
381	}
382
383      template<typename _Iterator, typename _Sequence, typename _Category>
384	_Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence,
385							_Category>> const& __it,
386	  const char* __name, _Is_iterator)
387	: _Parameter(__it.base(), __name, _Is_iterator{})
388	{
389	  _M_variant._M_iterator._M_type
390	    = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>);
391	  _M_variant._M_iterator._M_state
392	    = _S_reverse_state(_M_variant._M_iterator._M_state);
393	}
394
395      template<typename _Iterator>
396	_Parameter(std::move_iterator<_Iterator> const& __it,
397		   const char* __name, _Is_iterator)
398	: _Parameter(__it.base(), __name, _Is_iterator{})
399	{ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
400
401      template<typename _Iterator, typename _Sequence, typename _Category>
402	_Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence,
403						     _Category>> const& __it,
404	  const char* __name, _Is_iterator)
405	: _Parameter(__it.base(), __name, _Is_iterator{})
406      {
407	_M_variant._M_iterator._M_type
408	  = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>);
409      }
410
411    private:
412      _Iterator_state
413      _S_reverse_state(_Iterator_state __state)
414      {
415	  switch (__state)
416	    {
417	    case __begin:
418	      return __rend;
419	    case __middle:
420	      return __rmiddle;
421	    case __end:
422	      return __rbegin;
423	    default:
424	      return __state;
425	    }
426      }
427
428    public:
429#endif
430
431      template<typename _Sequence>
432	_Parameter(const _Safe_sequence<_Sequence>& __seq,
433		   const char* __name, _Is_sequence)
434	: _M_kind(__sequence), _M_variant()
435	{
436	  _M_variant._M_sequence._M_name = __name;
437	  _M_variant._M_sequence._M_address =
438	    static_cast<const _Sequence*>(std::__addressof(__seq));
439	  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
440	}
441
442      template<typename _Sequence>
443	_Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
444	: _M_kind(__sequence), _M_variant()
445	{
446	  _M_variant._M_sequence._M_name = __name;
447	  _M_variant._M_sequence._M_address = std::__addressof(__seq);
448	  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
449	}
450
451      template<typename _Iterator>
452	_Parameter(const _Iterator& __it, const char* __name,
453		   _Is_iterator_value_type)
454	: _M_kind(__iterator_value_type), _M_variant()
455	{
456	  _M_variant._M_iterator_value_type._M_name = __name;
457	  _M_variant._M_iterator_value_type._M_type =
458	    _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type);
459	}
460
461      template<typename _Type>
462	_Parameter(const _Type& __inst, const char* __name, _Is_instance)
463	: _M_kind(__instance), _M_variant()
464	{
465	  _M_variant._M_instance._M_name = __name;
466	  _M_variant._M_instance._M_address = &__inst;
467	  _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type);
468	}
469
470#if !_GLIBCXX_INLINE_VERSION
471      void
472      _M_print_field(const _Error_formatter* __formatter,
473		     const char* __name) const _GLIBCXX_DEPRECATED;
474
475      void
476      _M_print_description(const _Error_formatter* __formatter)
477	const _GLIBCXX_DEPRECATED;
478#endif
479    };
480
481    template<typename _Iterator>
482      _Error_formatter&
483      _M_iterator(const _Iterator& __it, const char* __name = 0)
484      {
485	if (_M_num_parameters < std::size_t(__max_parameters))
486	  _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
487							  _Is_iterator());
488	return *this;
489      }
490
491    template<typename _Iterator>
492      _Error_formatter&
493      _M_iterator_value_type(const _Iterator& __it,
494			     const char* __name = 0)
495      {
496	if (_M_num_parameters < __max_parameters)
497	  _M_parameters[_M_num_parameters++] =
498	    _Parameter(__it, __name, _Is_iterator_value_type());
499	return *this;
500      }
501
502    _Error_formatter&
503    _M_integer(long __value, const char* __name = 0)
504    {
505      if (_M_num_parameters < __max_parameters)
506	_M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
507      return *this;
508    }
509
510    _Error_formatter&
511    _M_string(const char* __value, const char* __name = 0)
512    {
513      if (_M_num_parameters < __max_parameters)
514	_M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
515      return *this;
516    }
517
518    template<typename _Sequence>
519      _Error_formatter&
520      _M_sequence(const _Sequence& __seq, const char* __name = 0)
521      {
522	if (_M_num_parameters < __max_parameters)
523	  _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
524							  _Is_sequence());
525	return *this;
526      }
527
528    template<typename _Type>
529      _Error_formatter&
530      _M_instance(const _Type& __inst, const char* __name = 0)
531      {
532	if (_M_num_parameters < __max_parameters)
533	  _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
534							  _Is_instance());
535	return *this;
536      }
537
538    _Error_formatter&
539    _M_message(const char* __text)
540    { _M_text = __text; return *this; }
541
542    // Kept const qualifier for backward compatibility, to keep the same
543    // exported symbol.
544    _Error_formatter&
545    _M_message(_Debug_msg_id __id) const throw ();
546
547    _GLIBCXX_NORETURN void
548    _M_error() const;
549
550#if !_GLIBCXX_INLINE_VERSION
551    template<typename _Tp>
552      void
553      _M_format_word(char*, int, const char*, _Tp)
554      const throw () _GLIBCXX_DEPRECATED;
555
556    void
557    _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED;
558
559    void
560    _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED;
561#endif
562
563  private:
564    _Error_formatter(const char* __file, unsigned int __line,
565		     const char* __function)
566    : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0)
567    , _M_function(__function)
568    { }
569
570#if !_GLIBCXX_INLINE_VERSION
571    void
572    _M_get_max_length() const throw () _GLIBCXX_DEPRECATED;
573#endif
574
575    enum { __max_parameters = 9 };
576
577    const char*		_M_file;
578    unsigned int	_M_line;
579    _Parameter		_M_parameters[__max_parameters];
580    unsigned int	_M_num_parameters;
581    const char*		_M_text;
582    const char*		_M_function;
583
584  public:
585    static _Error_formatter&
586    _S_at(const char* __file, unsigned int __line, const char* __function)
587    {
588      static _Error_formatter __formatter(__file, __line, __function);
589      return __formatter;
590    }
591  };
592} // namespace __gnu_debug
593
594#undef _GLIBCXX_TYPEID
595
596#endif
597