libstdc++
formatter.h
Go to the documentation of this file.
1 // Debug-mode error formatting implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2021 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
38 namespace std
39 {
40  class type_info;
41 }
42 # define _GLIBCXX_TYPEID(_Type) 0
43 #endif
44 
45 #if __cplusplus >= 201103L
46 namespace __gnu_cxx
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 
50 template<typename _Iterator, typename _Container>
51  class __normal_iterator;
52 
53 _GLIBCXX_END_NAMESPACE_VERSION
54 }
55 
56 namespace std
57 {
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
59 
60 template<typename _Iterator>
61  class reverse_iterator;
62 
63 template<typename _Iterator>
64  class move_iterator;
65 
66 _GLIBCXX_END_NAMESPACE_VERSION
67 }
68 #endif
69 
70 namespace __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>
85 
86  template<typename _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 _Type
206  {
207  const char* _M_name;
208  const type_info* _M_type;
209  };
210 
211  struct _Instance : _Type
212  {
213  const void* _M_address;
214  };
215 
216  union
217  {
218  // When _M_kind == __iterator
219  struct : _Instance
220  {
221  _Constness _M_constness;
222  _Iterator_state _M_state;
223  const void* _M_sequence;
224  const type_info* _M_seq_type;
225  } _M_iterator;
226 
227  // When _M_kind == __sequence
228  _Instance _M_sequence;
229 
230  // When _M_kind == __integer
231  struct
232  {
233  const char* _M_name;
234  long _M_value;
235  } _M_integer;
236 
237  // When _M_kind == __string
238  struct
239  {
240  const char* _M_name;
241  const char* _M_value;
242  } _M_string;
243 
244  // When _M_kind == __instance
245  _Instance _M_instance;
246 
247  // When _M_kind == __iterator_value_type
248  _Type _M_iterator_value_type;
249  } _M_variant;
250 
251  _Parameter() : _M_kind(__unused_param), _M_variant() { }
252 
253  _Parameter(long __value, const char* __name)
254  : _M_kind(__integer), _M_variant()
255  {
256  _M_variant._M_integer._M_name = __name;
257  _M_variant._M_integer._M_value = __value;
258  }
259 
260  _Parameter(const char* __value, const char* __name)
261  : _M_kind(__string), _M_variant()
262  {
263  _M_variant._M_string._M_name = __name;
264  _M_variant._M_string._M_value = __value;
265  }
266 
267  template<typename _Iterator, typename _Sequence, typename _Category>
268  _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it,
269  const char* __name, _Is_iterator)
270  : _M_kind(__iterator), _M_variant()
271  {
272  _M_variant._M_iterator._M_name = __name;
273  _M_variant._M_iterator._M_address = std::__addressof(__it);
274  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
275  _M_variant._M_iterator._M_constness =
276  __it._S_constant() ? __const_iterator : __mutable_iterator;
277  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
278  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
279 
280  if (__it._M_singular())
281  _M_variant._M_iterator._M_state = __singular;
282  else
283  {
284  if (__it._M_is_before_begin())
285  _M_variant._M_iterator._M_state = __before_begin;
286  else if (__it._M_is_end())
287  _M_variant._M_iterator._M_state = __end;
288  else if (__it._M_is_begin())
289  _M_variant._M_iterator._M_state = __begin;
290  else
291  _M_variant._M_iterator._M_state = __middle;
292  }
293  }
294 
295  template<typename _Iterator, typename _Sequence>
296  _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
297  const char* __name, _Is_iterator)
298  : _M_kind(__iterator), _M_variant()
299  {
300  _M_variant._M_iterator._M_name = __name;
301  _M_variant._M_iterator._M_address = std::__addressof(__it);
302  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
303  _M_variant._M_iterator._M_constness =
304  __it._S_constant() ? __const_iterator : __mutable_iterator;
305  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
306  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
307 
308  if (__it._M_singular())
309  _M_variant._M_iterator._M_state = __singular;
310  else
311  {
312  if (__it._M_is_end())
313  _M_variant._M_iterator._M_state = __end;
314  else if (__it._M_is_begin())
315  _M_variant._M_iterator._M_state = __begin;
316  else
317  _M_variant._M_iterator._M_state = __middle;
318  }
319  }
320 
321  template<typename _Type>
322  _Parameter(const _Type* const& __it, const char* __name, _Is_iterator)
323  : _M_kind(__iterator), _M_variant()
324  {
325  _M_variant._M_iterator._M_name = __name;
326  _M_variant._M_iterator._M_address = std::__addressof(__it);
327  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
328  _M_variant._M_iterator._M_constness = __const_iterator;
329  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
330  _M_variant._M_iterator._M_sequence = 0;
331  _M_variant._M_iterator._M_seq_type = 0;
332  }
333 
334  template<typename _Type>
335  _Parameter(_Type* const& __it, const char* __name, _Is_iterator)
336  : _M_kind(__iterator), _M_variant()
337  {
338  _M_variant._M_iterator._M_name = __name;
339  _M_variant._M_iterator._M_address = std::__addressof(__it);
340  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
341  _M_variant._M_iterator._M_constness = __mutable_iterator;
342  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
343  _M_variant._M_iterator._M_sequence = 0;
344  _M_variant._M_iterator._M_seq_type = 0;
345  }
346 
347  template<typename _Iterator>
348  _Parameter(_Iterator const& __it, const char* __name, _Is_iterator)
349  : _M_kind(__iterator), _M_variant()
350  {
351  _M_variant._M_iterator._M_name = __name;
352  _M_variant._M_iterator._M_address = std::__addressof(__it);
353  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
354  _M_variant._M_iterator._M_constness = __unknown_constness;
355  _M_variant._M_iterator._M_state =
356  __gnu_debug::__check_singular(__it) ? __singular : __unknown_state;
357  _M_variant._M_iterator._M_sequence = 0;
358  _M_variant._M_iterator._M_seq_type = 0;
359  }
360 
361 #if __cplusplus >= 201103L
362  // The following constructors are only defined in C++11 to take
363  // advantage of the constructor delegation feature.
364  template<typename _Iterator, typename _Container>
365  _Parameter(
366  __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it,
367  const char* __name, _Is_iterator)
368  : _Parameter(__it.base(), __name, _Is_iterator{})
369  { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
370 
371  template<typename _Iterator>
372  _Parameter(std::reverse_iterator<_Iterator> const& __it,
373  const char* __name, _Is_iterator)
374  : _Parameter(__it.base(), __name, _Is_iterator{})
375  {
376  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
377  _M_variant._M_iterator._M_state
378  = _S_reverse_state(_M_variant._M_iterator._M_state);
379  }
380 
381  template<typename _Iterator, typename _Sequence, typename _Category>
382  _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence,
383  _Category>> const& __it,
384  const char* __name, _Is_iterator)
385  : _Parameter(__it.base(), __name, _Is_iterator{})
386  {
387  _M_variant._M_iterator._M_type
388  = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>);
389  _M_variant._M_iterator._M_state
390  = _S_reverse_state(_M_variant._M_iterator._M_state);
391  }
392 
393  template<typename _Iterator>
394  _Parameter(std::move_iterator<_Iterator> const& __it,
395  const char* __name, _Is_iterator)
396  : _Parameter(__it.base(), __name, _Is_iterator{})
397  { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
398 
399  template<typename _Iterator, typename _Sequence, typename _Category>
400  _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence,
401  _Category>> const& __it,
402  const char* __name, _Is_iterator)
403  : _Parameter(__it.base(), __name, _Is_iterator{})
404  {
405  _M_variant._M_iterator._M_type
406  = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>);
407  }
408 
409  private:
410  _Iterator_state
411  _S_reverse_state(_Iterator_state __state)
412  {
413  switch (__state)
414  {
415  case __begin:
416  return __rend;
417  case __middle:
418  return __rmiddle;
419  case __end:
420  return __rbegin;
421  default:
422  return __state;
423  }
424  }
425 
426  public:
427 #endif
428 
429  template<typename _Sequence>
430  _Parameter(const _Safe_sequence<_Sequence>& __seq,
431  const char* __name, _Is_sequence)
432  : _M_kind(__sequence), _M_variant()
433  {
434  _M_variant._M_sequence._M_name = __name;
435  _M_variant._M_sequence._M_address =
436  static_cast<const _Sequence*>(std::__addressof(__seq));
437  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
438  }
439 
440  template<typename _Sequence>
441  _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
442  : _M_kind(__sequence), _M_variant()
443  {
444  _M_variant._M_sequence._M_name = __name;
445  _M_variant._M_sequence._M_address = std::__addressof(__seq);
446  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
447  }
448 
449  template<typename _Iterator>
450  _Parameter(const _Iterator& __it, const char* __name,
451  _Is_iterator_value_type)
452  : _M_kind(__iterator_value_type), _M_variant()
453  {
454  _M_variant._M_iterator_value_type._M_name = __name;
455  _M_variant._M_iterator_value_type._M_type =
456  _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type);
457  }
458 
459  template<typename _Type>
460  _Parameter(const _Type& __inst, const char* __name, _Is_instance)
461  : _M_kind(__instance), _M_variant()
462  {
463  _M_variant._M_instance._M_name = __name;
464  _M_variant._M_instance._M_address = &__inst;
465  _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type);
466  }
467 
468 #if !_GLIBCXX_INLINE_VERSION
469  void
470  _M_print_field(const _Error_formatter* __formatter,
471  const char* __name) const _GLIBCXX_DEPRECATED;
472 
473  void
474  _M_print_description(const _Error_formatter* __formatter)
475  const _GLIBCXX_DEPRECATED;
476 #endif
477  };
478 
479  template<typename _Iterator>
480  _Error_formatter&
481  _M_iterator(const _Iterator& __it, const char* __name = 0)
482  {
483  if (_M_num_parameters < std::size_t(__max_parameters))
484  _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
485  _Is_iterator());
486  return *this;
487  }
488 
489  template<typename _Iterator>
490  _Error_formatter&
491  _M_iterator_value_type(const _Iterator& __it,
492  const char* __name = 0)
493  {
494  if (_M_num_parameters < __max_parameters)
495  _M_parameters[_M_num_parameters++] =
496  _Parameter(__it, __name, _Is_iterator_value_type());
497  return *this;
498  }
499 
500  _Error_formatter&
501  _M_integer(long __value, const char* __name = 0)
502  {
503  if (_M_num_parameters < __max_parameters)
504  _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
505  return *this;
506  }
507 
508  _Error_formatter&
509  _M_string(const char* __value, const char* __name = 0)
510  {
511  if (_M_num_parameters < __max_parameters)
512  _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
513  return *this;
514  }
515 
516  template<typename _Sequence>
517  _Error_formatter&
518  _M_sequence(const _Sequence& __seq, const char* __name = 0)
519  {
520  if (_M_num_parameters < __max_parameters)
521  _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
522  _Is_sequence());
523  return *this;
524  }
525 
526  template<typename _Type>
527  _Error_formatter&
528  _M_instance(const _Type& __inst, const char* __name = 0)
529  {
530  if (_M_num_parameters < __max_parameters)
531  _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
532  _Is_instance());
533  return *this;
534  }
535 
536  _Error_formatter&
537  _M_message(const char* __text)
538  { _M_text = __text; return *this; }
539 
540  // Kept const qualifier for backward compatibility, to keep the same
541  // exported symbol.
542  _Error_formatter&
543  _M_message(_Debug_msg_id __id) const throw ();
544 
545  _GLIBCXX_NORETURN void
546  _M_error() const;
547 
548 #if !_GLIBCXX_INLINE_VERSION
549  template<typename _Tp>
550  void
551  _M_format_word(char*, int, const char*, _Tp)
552  const throw () _GLIBCXX_DEPRECATED;
553 
554  void
555  _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED;
556 
557  void
558  _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED;
559 #endif
560 
561  private:
562  _Error_formatter(const char* __file, unsigned int __line,
563  const char* __function)
564  : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0)
565  , _M_function(__function)
566  { }
567 
568 #if !_GLIBCXX_INLINE_VERSION
569  void
570  _M_get_max_length() const throw () _GLIBCXX_DEPRECATED;
571 #endif
572 
573  enum { __max_parameters = 9 };
574 
575  const char* _M_file;
576  unsigned int _M_line;
577  _Parameter _M_parameters[__max_parameters];
578  unsigned int _M_num_parameters;
579  const char* _M_text;
580  const char* _M_function;
581 
582  public:
583  static _Error_formatter&
584  _S_at(const char* __file, unsigned int __line, const char* __function)
585  {
586  static _Error_formatter __formatter(__file, __line, __function);
587  return __formatter;
588  }
589  };
590 } // namespace __gnu_debug
591 
592 #undef _GLIBCXX_TYPEID
593 
594 #endif
Base class for constructing a safe sequence type that tracks iterators that reference it...
Definition: formatter.h:87
Traits class for iterators.
constexpr bool __check_singular(_Tp *const &__ptr)
GNU debug classes for public use.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
GNU extensions for public use.
Safe iterator wrapper.
Definition: formatter.h:84
Part of RTTI.
Definition: typeinfo:88
ISO C++ entities toplevel namespace is std.