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