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