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