libstdc++
formatter.h
Go to the documentation of this file.
1 // Debug-mode error formatting implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2018 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 #include <bits/cpp_type_traits.h>
34 
35 #if __cpp_rtti
36 # include <typeinfo>
37 # define _GLIBCXX_TYPEID(_Type) &typeid(_Type)
38 #else
39 namespace std
40 {
41  class type_info;
42 }
43 # define _GLIBCXX_TYPEID(_Type) 0
44 #endif
45 
46 namespace __gnu_debug
47 {
48  using std::type_info;
49 
50  template<typename _Iterator>
51  bool __check_singular(const _Iterator&);
52 
53  class _Safe_sequence_base;
54 
55  template<typename _Iterator, typename _Sequence>
57 
58  template<typename _Iterator, typename _Sequence>
60 
61  template<typename _Sequence>
63 
64  enum _Debug_msg_id
65  {
66  // General checks
67  __msg_valid_range,
68  __msg_insert_singular,
69  __msg_insert_different,
70  __msg_erase_bad,
71  __msg_erase_different,
72  __msg_subscript_oob,
73  __msg_empty,
74  __msg_unpartitioned,
75  __msg_unpartitioned_pred,
76  __msg_unsorted,
77  __msg_unsorted_pred,
78  __msg_not_heap,
79  __msg_not_heap_pred,
80  // std::bitset checks
81  __msg_bad_bitset_write,
82  __msg_bad_bitset_read,
83  __msg_bad_bitset_flip,
84  // std::list checks
85  __msg_self_splice,
86  __msg_splice_alloc,
87  __msg_splice_bad,
88  __msg_splice_other,
89  __msg_splice_overlap,
90  // iterator checks
91  __msg_init_singular,
92  __msg_init_copy_singular,
93  __msg_init_const_singular,
94  __msg_copy_singular,
95  __msg_bad_deref,
96  __msg_bad_inc,
97  __msg_bad_dec,
98  __msg_iter_subscript_oob,
99  __msg_advance_oob,
100  __msg_retreat_oob,
101  __msg_iter_compare_bad,
102  __msg_compare_different,
103  __msg_iter_order_bad,
104  __msg_order_different,
105  __msg_distance_bad,
106  __msg_distance_different,
107  // istream_iterator
108  __msg_deref_istream,
109  __msg_inc_istream,
110  // ostream_iterator
111  __msg_output_ostream,
112  // istreambuf_iterator
113  __msg_deref_istreambuf,
114  __msg_inc_istreambuf,
115  // forward_list
116  __msg_insert_after_end,
117  __msg_erase_after_bad,
118  __msg_valid_range2,
119  // unordered container local iterators
120  __msg_local_iter_compare_bad,
121  __msg_non_empty_range,
122  // self move assign
123  __msg_self_move_assign,
124  // unordered container buckets
125  __msg_bucket_index_oob,
126  __msg_valid_load_factor,
127  // others
128  __msg_equal_allocs,
129  __msg_insert_range_from_self,
130  __msg_irreflexive_ordering
131  };
132 
133  class _Error_formatter
134  {
135  // Tags denoting the type of parameter for construction
136  struct _Is_iterator { };
137  struct _Is_iterator_value_type { };
138  struct _Is_sequence { };
139  struct _Is_instance { };
140 
141  public:
142  /// Whether an iterator is constant, mutable, or unknown
143  enum _Constness
144  {
145  __unknown_constness,
146  __const_iterator,
147  __mutable_iterator,
148  __last_constness
149  };
150 
151  // The state of the iterator (fine-grained), if we know it.
152  enum _Iterator_state
153  {
154  __unknown_state,
155  __singular, // singular, may still be attached to a sequence
156  __begin, // dereferenceable, and at the beginning
157  __middle, // dereferenceable, not at the beginning
158  __end, // past-the-end, may be at beginning if sequence empty
159  __before_begin, // before begin
160  __last_state
161  };
162 
163  // A parameter that may be referenced by an error message
164  struct _Parameter
165  {
166  enum
167  {
168  __unused_param,
169  __iterator,
170  __sequence,
171  __integer,
172  __string,
173  __instance,
174  __iterator_value_type
175  } _M_kind;
176 
177  struct _Type
178  {
179  const char* _M_name;
180  const type_info* _M_type;
181  };
182 
183  struct _Instance : _Type
184  {
185  const void* _M_address;
186  };
187 
188  union
189  {
190  // When _M_kind == __iterator
191  struct : _Instance
192  {
193  _Constness _M_constness;
194  _Iterator_state _M_state;
195  const void* _M_sequence;
196  const type_info* _M_seq_type;
197  } _M_iterator;
198 
199  // When _M_kind == __sequence
200  _Instance _M_sequence;
201 
202  // When _M_kind == __integer
203  struct
204  {
205  const char* _M_name;
206  long _M_value;
207  } _M_integer;
208 
209  // When _M_kind == __string
210  struct
211  {
212  const char* _M_name;
213  const char* _M_value;
214  } _M_string;
215 
216  // When _M_kind == __instance
217  _Instance _M_instance;
218 
219  // When _M_kind == __iterator_value_type
220  _Type _M_iterator_value_type;
221  } _M_variant;
222 
223  _Parameter() : _M_kind(__unused_param), _M_variant() { }
224 
225  _Parameter(long __value, const char* __name)
226  : _M_kind(__integer), _M_variant()
227  {
228  _M_variant._M_integer._M_name = __name;
229  _M_variant._M_integer._M_value = __value;
230  }
231 
232  _Parameter(const char* __value, const char* __name)
233  : _M_kind(__string), _M_variant()
234  {
235  _M_variant._M_string._M_name = __name;
236  _M_variant._M_string._M_value = __value;
237  }
238 
239  template<typename _Iterator, typename _Sequence>
240  _Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it,
241  const char* __name, _Is_iterator)
242  : _M_kind(__iterator), _M_variant()
243  {
244  _M_variant._M_iterator._M_name = __name;
245  _M_variant._M_iterator._M_address = std::__addressof(__it);
246  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
247  _M_variant._M_iterator._M_constness =
248  std::__are_same<_Safe_iterator<_Iterator, _Sequence>,
249  typename _Sequence::iterator>::
250  __value ? __mutable_iterator : __const_iterator;
251  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
252  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
253 
254  if (__it._M_singular())
255  _M_variant._M_iterator._M_state = __singular;
256  else
257  {
258  if (__it._M_is_before_begin())
259  _M_variant._M_iterator._M_state = __before_begin;
260  else if (__it._M_is_end())
261  _M_variant._M_iterator._M_state = __end;
262  else if (__it._M_is_begin())
263  _M_variant._M_iterator._M_state = __begin;
264  else
265  _M_variant._M_iterator._M_state = __middle;
266  }
267  }
268 
269  template<typename _Iterator, typename _Sequence>
270  _Parameter(_Safe_local_iterator<_Iterator, _Sequence> 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(__it);
277  _M_variant._M_iterator._M_constness =
278  std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>,
279  typename _Sequence::local_iterator>::
280  __value ? __mutable_iterator : __const_iterator;
281  _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
282  _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
283 
284  if (__it._M_singular())
285  _M_variant._M_iterator._M_state = __singular;
286  else
287  {
288  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 _Type>
298  _Parameter(const _Type* const& __it, const char* __name, _Is_iterator)
299  : _M_kind(__iterator), _M_variant()
300  {
301  _M_variant._M_iterator._M_name = __name;
302  _M_variant._M_iterator._M_address = std::__addressof(__it);
303  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
304  _M_variant._M_iterator._M_constness = __const_iterator;
305  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
306  _M_variant._M_iterator._M_sequence = 0;
307  _M_variant._M_iterator._M_seq_type = 0;
308  }
309 
310  template<typename _Type>
311  _Parameter(_Type* const& __it, const char* __name, _Is_iterator)
312  : _M_kind(__iterator), _M_variant()
313  {
314  _M_variant._M_iterator._M_name = __name;
315  _M_variant._M_iterator._M_address = std::__addressof(__it);
316  _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
317  _M_variant._M_iterator._M_constness = __mutable_iterator;
318  _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
319  _M_variant._M_iterator._M_sequence = 0;
320  _M_variant._M_iterator._M_seq_type = 0;
321  }
322 
323  template<typename _Iterator>
324  _Parameter(_Iterator 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 = __unknown_constness;
331  _M_variant._M_iterator._M_state =
332  __gnu_debug::__check_singular(__it) ? __singular : __unknown_state;
333  _M_variant._M_iterator._M_sequence = 0;
334  _M_variant._M_iterator._M_seq_type = 0;
335  }
336 
337  template<typename _Sequence>
338  _Parameter(const _Safe_sequence<_Sequence>& __seq,
339  const char* __name, _Is_sequence)
340  : _M_kind(__sequence), _M_variant()
341  {
342  _M_variant._M_sequence._M_name = __name;
343  _M_variant._M_sequence._M_address =
344  static_cast<const _Sequence*>(std::__addressof(__seq));
345  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
346  }
347 
348  template<typename _Sequence>
349  _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
350  : _M_kind(__sequence), _M_variant()
351  {
352  _M_variant._M_sequence._M_name = __name;
353  _M_variant._M_sequence._M_address = std::__addressof(__seq);
354  _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
355  }
356 
357  template<typename _Iterator>
358  _Parameter(const _Iterator& __it, const char* __name,
359  _Is_iterator_value_type)
360  : _M_kind(__iterator_value_type), _M_variant()
361  {
362  _M_variant._M_iterator_value_type._M_name = __name;
363  _M_variant._M_iterator_value_type._M_type =
364  _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type);
365  }
366 
367  template<typename _Type>
368  _Parameter(const _Type& __inst, const char* __name, _Is_instance)
369  : _M_kind(__instance), _M_variant()
370  {
371  _M_variant._M_instance._M_name = __name;
372  _M_variant._M_instance._M_address = &__inst;
373  _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type);
374  }
375 
376 #if !_GLIBCXX_INLINE_VERSION
377  void
378  _M_print_field(const _Error_formatter* __formatter,
379  const char* __name) const _GLIBCXX_DEPRECATED;
380 
381  void
382  _M_print_description(const _Error_formatter* __formatter)
383  const _GLIBCXX_DEPRECATED;
384 #endif
385  };
386 
387  template<typename _Iterator>
388  _Error_formatter&
389  _M_iterator(const _Iterator& __it, const char* __name = 0)
390  {
391  if (_M_num_parameters < std::size_t(__max_parameters))
392  _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
393  _Is_iterator());
394  return *this;
395  }
396 
397  template<typename _Iterator>
398  _Error_formatter&
399  _M_iterator_value_type(const _Iterator& __it,
400  const char* __name = 0)
401  {
402  if (_M_num_parameters < __max_parameters)
403  _M_parameters[_M_num_parameters++] =
404  _Parameter(__it, __name, _Is_iterator_value_type());
405  return *this;
406  }
407 
408  _Error_formatter&
409  _M_integer(long __value, const char* __name = 0)
410  {
411  if (_M_num_parameters < __max_parameters)
412  _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
413  return *this;
414  }
415 
416  _Error_formatter&
417  _M_string(const char* __value, const char* __name = 0)
418  {
419  if (_M_num_parameters < __max_parameters)
420  _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
421  return *this;
422  }
423 
424  template<typename _Sequence>
425  _Error_formatter&
426  _M_sequence(const _Sequence& __seq, const char* __name = 0)
427  {
428  if (_M_num_parameters < __max_parameters)
429  _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
430  _Is_sequence());
431  return *this;
432  }
433 
434  template<typename _Type>
435  _Error_formatter&
436  _M_instance(const _Type& __inst, const char* __name = 0)
437  {
438  if (_M_num_parameters < __max_parameters)
439  _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
440  _Is_instance());
441  return *this;
442  }
443 
444  _Error_formatter&
445  _M_message(const char* __text)
446  { _M_text = __text; return *this; }
447 
448  // Kept const qualifier for backward compatibility, to keep the same
449  // exported symbol.
450  _Error_formatter&
451  _M_message(_Debug_msg_id __id) const throw ();
452 
453  _GLIBCXX_NORETURN void
454  _M_error() const;
455 
456 #if !_GLIBCXX_INLINE_VERSION
457  template<typename _Tp>
458  void
459  _M_format_word(char*, int, const char*, _Tp)
460  const throw () _GLIBCXX_DEPRECATED;
461 
462  void
463  _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED;
464 
465  void
466  _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED;
467 #endif
468 
469  private:
470  _Error_formatter(const char* __file, unsigned int __line)
471  : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0)
472  { }
473 
474 #if !_GLIBCXX_INLINE_VERSION
475  void
476  _M_get_max_length() const throw () _GLIBCXX_DEPRECATED;
477 #endif
478 
479  enum { __max_parameters = 9 };
480 
481  const char* _M_file;
482  unsigned int _M_line;
483  _Parameter _M_parameters[__max_parameters];
484  unsigned int _M_num_parameters;
485  const char* _M_text;
486 
487  public:
488  static _Error_formatter&
489  _M_at(const char* __file, unsigned int __line)
490  {
491  static _Error_formatter __formatter(__file, __line);
492  return __formatter;
493  }
494  };
495 } // namespace __gnu_debug
496 
497 #undef _GLIBCXX_TYPEID
498 
499 #endif
Part of RTTI.
Definition: typeinfo:88
GNU debug classes for public use.
Safe iterator wrapper.
Definition: formatter.h:56
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:47
Base class for constructing a safe sequence type that tracks iterators that reference it.
Definition: formatter.h:62
bool __check_singular(const _Tp *__ptr)
Definition: functions.h:67
ISO C++ entities toplevel namespace is std.
Safe iterator wrapper.
Definition: formatter.h:59