libstdc++
formatter.h
Go to the documentation of this file.
1 // Debug-mode error formatting implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2019 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>
81 
82  template<typename _Iterator, typename _Sequence>
84 
85  template<typename _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  _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
ISO C++ entities toplevel namespace is std.
Safe iterator wrapper.
Definition: formatter.h:80
Part of RTTI.
Definition: typeinfo:88
bool __check_singular(const _Tp *__ptr)
Definition: functions.h:66
Base class for constructing a safe sequence type that tracks iterators that reference it...
Definition: formatter.h:86
GNU debug classes for public use.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:47
GNU extensions for public use.
Safe iterator wrapper.
Definition: formatter.h:83