xref: /openbsd/gnu/gcc/libstdc++-v3/src/debug.cc (revision d415bd75)
1 // Debugging mode support code -*- C++ -*-
2 
3 // Copyright (C) 2003, 2004, 2005, 2006
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 // USA.
21 
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30 
31 #include <debug/debug.h>
32 #include <debug/safe_sequence.h>
33 #include <debug/safe_iterator.h>
34 #include <algorithm>
35 #include <cassert>
36 #include <cstring>
37 #include <cctype>
38 
39 using namespace std;
40 
41 namespace
42 {
43   __gnu_cxx::__mutex safe_base_mutex;
44 } // anonymous namespace
45 
46 namespace __gnu_debug
47 {
48   static const char* _S_debug_messages[] =
49   {
50     "function requires a valid iterator range [%1.name;, %2.name;)",
51     "attempt to insert into container with a singular iterator",
52     "attempt to insert into container with an iterator"
53     " from a different container",
54     "attempt to erase from container with a %2.state; iterator",
55     "attempt to erase from container with an iterator"
56     " from a different container",
57     "attempt to subscript container with out-of-bounds index %2;,"
58     " but container only holds %3; elements",
59     "attempt to access an element in an empty container",
60     "elements in iterator range [%1.name;, %2.name;)"
61     " are not partitioned by the value %3;",
62     "elements in iterator range [%1.name;, %2.name;)"
63     " are not partitioned by the predicate %3; and value %4;",
64     "elements in iterator range [%1.name;, %2.name;) are not sorted",
65     "elements in iterator range [%1.name;, %2.name;)"
66     " are not sorted according to the predicate %3;",
67     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
68     "elements in iterator range [%1.name;, %2.name;)"
69     " do not form a heap with respect to the predicate %3;",
70     "attempt to write through a singular bitset reference",
71     "attempt to read from a singular bitset reference",
72     "attempt to flip a singular bitset reference",
73     "attempt to splice a list into itself",
74     "attempt to splice lists with inequal allocators",
75     "attempt to splice elements referenced by a %1.state; iterator",
76     "attempt to splice an iterator from a different container",
77     "splice destination %1.name;"
78     " occurs within source range [%2.name;, %3.name;)",
79     "attempt to initialize an iterator that will immediately become singular",
80     "attempt to copy-construct an iterator from a singular iterator",
81     "attempt to construct a constant iterator"
82     " from a singular mutable iterator",
83     "attempt to copy from a singular iterator",
84     "attempt to dereference a %1.state; iterator",
85     "attempt to increment a %1.state; iterator",
86     "attempt to decrement a %1.state; iterator",
87     "attempt to subscript a %1.state; iterator %2; step from"
88     " its current position, which falls outside its dereferenceable range",
89     "attempt to advance a %1.state; iterator %2; steps,"
90     " which falls outside its valid range",
91     "attempt to retreat a %1.state; iterator %2; steps,"
92     " which falls outside its valid range",
93     "attempt to compare a %1.state; iterator to a %2.state; iterator",
94     "attempt to compare iterators from different sequences",
95     "attempt to order a %1.state; iterator to a %2.state; iterator",
96     "attempt to order iterators from different sequences",
97     "attempt to compute the difference between a %1.state;"
98     " iterator to a %2.state; iterator",
99     "attempt to compute the different between two iterators"
100     " from different sequences",
101     "attempt to dereference an end-of-stream istream_iterator",
102     "attempt to increment an end-of-stream istream_iterator",
103     "attempt to output via an ostream_iterator with no associated stream",
104     "attempt to dereference an end-of-stream istreambuf_iterator"
105     " (this is a GNU extension)",
106     "attempt to increment an end-of-stream istreambuf_iterator"
107   };
108 
109   void
110   _Safe_sequence_base::
111   _M_detach_all()
112   {
113     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
114     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
115       {
116 	_Safe_iterator_base* __old = __iter;
117 	__iter = __iter->_M_next;
118 	__old->_M_detach_single();
119       }
120 
121     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
122       {
123 	_Safe_iterator_base* __old = __iter2;
124 	__iter2 = __iter2->_M_next;
125 	__old->_M_detach_single();
126       }
127   }
128 
129   void
130   _Safe_sequence_base::
131   _M_detach_singular()
132   {
133     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
134     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
135       {
136 	_Safe_iterator_base* __old = __iter;
137 	__iter = __iter->_M_next;
138 	if (__old->_M_singular())
139 	  __old->_M_detach_single();
140       }
141 
142     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
143       {
144 	_Safe_iterator_base* __old = __iter2;
145 	__iter2 = __iter2->_M_next;
146 	if (__old->_M_singular())
147 	  __old->_M_detach_single();
148       }
149   }
150 
151   void
152   _Safe_sequence_base::
153   _M_revalidate_singular()
154   {
155     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
156     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
157 	 __iter = __iter->_M_next)
158       __iter->_M_version = _M_version;
159 
160     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
161 	 __iter2 = __iter2->_M_next)
162       __iter2->_M_version = _M_version;
163   }
164 
165   void
166   _Safe_sequence_base::
167   _M_swap(_Safe_sequence_base& __x)
168   {
169     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
170     swap(_M_iterators, __x._M_iterators);
171     swap(_M_const_iterators, __x._M_const_iterators);
172     swap(_M_version, __x._M_version);
173     _Safe_iterator_base* __iter;
174     for (__iter = _M_iterators; __iter; __iter = __iter->_M_next)
175       __iter->_M_sequence = this;
176     for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next)
177       __iter->_M_sequence = &__x;
178     for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next)
179       __iter->_M_sequence = this;
180     for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
181       __iter->_M_sequence = &__x;
182   }
183 
184   __gnu_cxx::__mutex&
185   _Safe_sequence_base::
186   _M_get_mutex()
187   { return safe_base_mutex; }
188 
189   void
190   _Safe_iterator_base::
191   _M_attach(_Safe_sequence_base* __seq, bool __constant)
192   {
193     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
194     _M_attach_single(__seq, __constant);
195   }
196 
197   void
198   _Safe_iterator_base::
199   _M_attach_single(_Safe_sequence_base* __seq, bool __constant)
200   {
201     _M_detach_single();
202 
203     // Attach to the new sequence (if there is one)
204     if (__seq)
205       {
206 	_M_sequence = __seq;
207 	_M_version = _M_sequence->_M_version;
208 	_M_prior = 0;
209 	if (__constant)
210 	  {
211 	    _M_next = _M_sequence->_M_const_iterators;
212 	    if (_M_next)
213 	      _M_next->_M_prior = this;
214 	    _M_sequence->_M_const_iterators = this;
215 	  }
216 	else
217 	  {
218 	    _M_next = _M_sequence->_M_iterators;
219 	    if (_M_next)
220 	      _M_next->_M_prior = this;
221 	    _M_sequence->_M_iterators = this;
222 	  }
223       }
224   }
225 
226   void
227   _Safe_iterator_base::
228   _M_detach()
229   {
230     __gnu_cxx::__scoped_lock sentry(safe_base_mutex);
231     _M_detach_single();
232   }
233 
234   void
235   _Safe_iterator_base::
236   _M_detach_single()
237   {
238     if (_M_sequence)
239       {
240 	// Remove us from this sequence's list
241 	if (_M_prior)
242 	  _M_prior->_M_next = _M_next;
243 	if (_M_next)
244 	  _M_next->_M_prior = _M_prior;
245 
246 	if (_M_sequence->_M_const_iterators == this)
247 	  _M_sequence->_M_const_iterators = _M_next;
248 	if (_M_sequence->_M_iterators == this)
249 	  _M_sequence->_M_iterators = _M_next;
250       }
251 
252     _M_sequence = 0;
253     _M_version = 0;
254     _M_prior = 0;
255     _M_next = 0;
256   }
257 
258   bool
259   _Safe_iterator_base::
260   _M_singular() const
261   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
262 
263   bool
264   _Safe_iterator_base::
265   _M_can_compare(const _Safe_iterator_base& __x) const
266   {
267     return (!_M_singular()
268 	    && !__x._M_singular() && _M_sequence == __x._M_sequence);
269   }
270 
271   __gnu_cxx::__mutex&
272   _Safe_iterator_base::
273   _M_get_mutex()
274   { return safe_base_mutex; }
275 
276   void
277   _Error_formatter::_Parameter::
278   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
279   {
280     assert(this->_M_kind != _Parameter::__unused_param);
281     const int __bufsize = 64;
282     char __buf[__bufsize];
283 
284     if (_M_kind == __iterator)
285       {
286 	if (strcmp(__name, "name") == 0)
287 	  {
288 	    assert(_M_variant._M_iterator._M_name);
289 	    __formatter->_M_print_word(_M_variant._M_iterator._M_name);
290 	  }
291 	else if (strcmp(__name, "address") == 0)
292 	  {
293 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
294 					_M_variant._M_iterator._M_address);
295 	    __formatter->_M_print_word(__buf);
296 	  }
297 	else if (strcmp(__name, "type") == 0)
298 	  {
299 	    assert(_M_variant._M_iterator._M_type);
300 	    // TBD: demangle!
301 	    __formatter->_M_print_word(_M_variant._M_iterator._M_type->name());
302 	  }
303 	else if (strcmp(__name, "constness") == 0)
304 	  {
305 	    static const char* __constness_names[__last_constness] =
306 	      {
307 		"<unknown>",
308 		"constant",
309 		"mutable"
310 	      };
311 	    __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]);
312 	  }
313 	else if (strcmp(__name, "state") == 0)
314 	  {
315 	    static const char* __state_names[__last_state] =
316 	      {
317 		"<unknown>",
318 		"singular",
319 		"dereferenceable (start-of-sequence)",
320 		"dereferenceable",
321 		"past-the-end"
322 	      };
323 	    __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]);
324 	  }
325 	else if (strcmp(__name, "sequence") == 0)
326 	  {
327 	    assert(_M_variant._M_iterator._M_sequence);
328 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
329 					_M_variant._M_iterator._M_sequence);
330 	    __formatter->_M_print_word(__buf);
331 	  }
332 	else if (strcmp(__name, "seq_type") == 0)
333 	  {
334 	    // TBD: demangle!
335 	    assert(_M_variant._M_iterator._M_seq_type);
336 	    __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name());
337 	  }
338 	else
339 	  assert(false);
340       }
341     else if (_M_kind == __sequence)
342       {
343 	if (strcmp(__name, "name") == 0)
344 	  {
345 	    assert(_M_variant._M_sequence._M_name);
346 	    __formatter->_M_print_word(_M_variant._M_sequence._M_name);
347 	  }
348 	else if (strcmp(__name, "address") == 0)
349 	  {
350 	    assert(_M_variant._M_sequence._M_address);
351 	    __formatter->_M_format_word(__buf, __bufsize, "%p",
352 					_M_variant._M_sequence._M_address);
353 	    __formatter->_M_print_word(__buf);
354 	  }
355 	else if (strcmp(__name, "type") == 0)
356 	  {
357 	    // TBD: demangle!
358 	    assert(_M_variant._M_sequence._M_type);
359 	    __formatter->_M_print_word(_M_variant._M_sequence._M_type->name());
360 	  }
361 	else
362 	  assert(false);
363       }
364     else if (_M_kind == __integer)
365       {
366 	if (strcmp(__name, "name") == 0)
367 	  {
368 	    assert(_M_variant._M_integer._M_name);
369 	    __formatter->_M_print_word(_M_variant._M_integer._M_name);
370 	  }
371 	else
372 	assert(false);
373       }
374     else if (_M_kind == __string)
375       {
376 	if (strcmp(__name, "name") == 0)
377 	  {
378 	    assert(_M_variant._M_string._M_name);
379 	    __formatter->_M_print_word(_M_variant._M_string._M_name);
380 	  }
381 	else
382 	  assert(false);
383       }
384     else
385       {
386 	assert(false);
387       }
388   }
389 
390   void
391   _Error_formatter::_Parameter::
392   _M_print_description(const _Error_formatter* __formatter) const
393   {
394     const int __bufsize = 128;
395     char __buf[__bufsize];
396 
397     if (_M_kind == __iterator)
398       {
399 	__formatter->_M_print_word("iterator ");
400 	if (_M_variant._M_iterator._M_name)
401 	  {
402 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
403 					_M_variant._M_iterator._M_name);
404 	    __formatter->_M_print_word(__buf);
405 	  }
406 
407 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
408 				    _M_variant._M_iterator._M_address);
409 	__formatter->_M_print_word(__buf);
410 	if (_M_variant._M_iterator._M_type)
411 	  {
412 	    __formatter->_M_print_word("type = ");
413 	    _M_print_field(__formatter, "type");
414 
415 	    if (_M_variant._M_iterator._M_constness != __unknown_constness)
416 	      {
417 		__formatter->_M_print_word(" (");
418 		_M_print_field(__formatter, "constness");
419 		__formatter->_M_print_word(" iterator)");
420 	      }
421 	    __formatter->_M_print_word(";\n");
422 	  }
423 
424 	if (_M_variant._M_iterator._M_state != __unknown_state)
425 	  {
426 	    __formatter->_M_print_word("  state = ");
427 	    _M_print_field(__formatter, "state");
428 	    __formatter->_M_print_word(";\n");
429 	  }
430 
431 	if (_M_variant._M_iterator._M_sequence)
432 	  {
433 	    __formatter->_M_print_word("  references sequence ");
434 	    if (_M_variant._M_iterator._M_seq_type)
435 	      {
436 		__formatter->_M_print_word("with type `");
437 		_M_print_field(__formatter, "seq_type");
438 		__formatter->_M_print_word("' ");
439 	      }
440 
441 	    __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
442 					_M_variant._M_sequence._M_address);
443 	    __formatter->_M_print_word(__buf);
444 	  }
445 	__formatter->_M_print_word("}\n");
446       }
447     else if (_M_kind == __sequence)
448       {
449 	__formatter->_M_print_word("sequence ");
450 	if (_M_variant._M_sequence._M_name)
451 	  {
452 	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
453 					_M_variant._M_sequence._M_name);
454 	    __formatter->_M_print_word(__buf);
455 	  }
456 
457 	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
458 				    _M_variant._M_sequence._M_address);
459 	__formatter->_M_print_word(__buf);
460 
461 	if (_M_variant._M_sequence._M_type)
462 	  {
463 	    __formatter->_M_print_word("  type = ");
464 	    _M_print_field(__formatter, "type");
465 	    __formatter->_M_print_word(";\n");
466 	  }
467 	__formatter->_M_print_word("}\n");
468       }
469   }
470 
471   const _Error_formatter&
472   _Error_formatter::_M_message(_Debug_msg_id __id) const
473   { return this->_M_message(_S_debug_messages[__id]); }
474 
475   void
476   _Error_formatter::_M_error() const
477   {
478     const int __bufsize = 128;
479     char __buf[__bufsize];
480 
481     // Emit file & line number information
482     _M_column = 1;
483     _M_wordwrap = false;
484     if (_M_file)
485       {
486 	_M_format_word(__buf, __bufsize, "%s:", _M_file);
487 	_M_print_word(__buf);
488 	_M_column += strlen(__buf);
489       }
490 
491     if (_M_line > 0)
492       {
493 	_M_format_word(__buf, __bufsize, "%u:", _M_line);
494 	_M_print_word(__buf);
495 	_M_column += strlen(__buf);
496       }
497 
498     _M_wordwrap = true;
499     _M_print_word("error: ");
500 
501     // Print the error message
502     assert(_M_text);
503     _M_print_string(_M_text);
504     _M_print_word(".\n");
505 
506     // Emit descriptions of the objects involved in the operation
507     _M_wordwrap = false;
508     bool __has_noninteger_parameters = false;
509     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
510       {
511 	if (_M_parameters[__i]._M_kind == _Parameter::__iterator
512 	    || _M_parameters[__i]._M_kind == _Parameter::__sequence)
513 	  {
514 	    if (!__has_noninteger_parameters)
515 	      {
516 		_M_first_line = true;
517 		_M_print_word("\nObjects involved in the operation:\n");
518 		__has_noninteger_parameters = true;
519 	      }
520 	    _M_parameters[__i]._M_print_description(this);
521 	  }
522       }
523 
524     abort();
525   }
526 
527   template<typename _Tp>
528     void
529     _Error_formatter::_M_format_word(char* __buf,
530 				     int __n __attribute__ ((__unused__)),
531 				     const char* __fmt, _Tp __s) const
532     {
533 #ifdef _GLIBCXX_USE_C99
534       std::snprintf(__buf, __n, __fmt, __s);
535 #else
536       std::sprintf(__buf, __fmt, __s);
537 #endif
538     }
539 
540 
541   void
542   _Error_formatter::_M_print_word(const char* __word) const
543   {
544     if (!_M_wordwrap)
545       {
546 	fprintf(stderr, "%s", __word);
547 	return;
548       }
549 
550     size_t __length = strlen(__word);
551     if (__length == 0)
552       return;
553 
554     if ((_M_column + __length < _M_max_length)
555 	|| (__length >= _M_max_length && _M_column == 1))
556       {
557 	// If this isn't the first line, indent
558 	if (_M_column == 1 && !_M_first_line)
559 	  {
560 	    char __spacing[_M_indent + 1];
561 	    for (int i = 0; i < _M_indent; ++i)
562 	      __spacing[i] = ' ';
563 	    __spacing[_M_indent] = '\0';
564 	    fprintf(stderr, "%s", __spacing);
565 	    _M_column += _M_indent;
566 	  }
567 
568 	fprintf(stderr, "%s", __word);
569 	_M_column += __length;
570 
571 	if (__word[__length - 1] == '\n')
572 	  {
573 	    _M_first_line = false;
574 	    _M_column = 1;
575 	  }
576       }
577     else
578       {
579 	_M_column = 1;
580 	_M_print_word("\n");
581 	_M_print_word(__word);
582       }
583   }
584 
585   void
586   _Error_formatter::
587   _M_print_string(const char* __string) const
588   {
589     const char* __start = __string;
590     const char* __finish = __start;
591     const int __bufsize = 128;
592     char __buf[__bufsize];
593 
594     while (*__start)
595       {
596 	if (*__start != '%')
597 	  {
598 	    // [__start, __finish) denotes the next word
599 	    __finish = __start;
600 	    while (isalnum(*__finish))
601 	      ++__finish;
602 	    if (__start == __finish)
603 	      ++__finish;
604 	    if (isspace(*__finish))
605 	      ++__finish;
606 
607 	    const ptrdiff_t __len = __finish - __start;
608 	    assert(__len < __bufsize);
609 	    memcpy(__buf, __start, __len);
610 	    __buf[__len] = '\0';
611 	    _M_print_word(__buf);
612 	    __start = __finish;
613 
614 	    // Skip extra whitespace
615 	    while (*__start == ' ')
616 	      ++__start;
617 
618 	    continue;
619 	  }
620 
621 	++__start;
622 	assert(*__start);
623 	if (*__start == '%')
624 	  {
625 	    _M_print_word("%");
626 	    ++__start;
627 	    continue;
628 	  }
629 
630 	// Get the parameter number
631 	assert(*__start >= '1' && *__start <= '9');
632 	size_t __param = *__start - '0';
633 	--__param;
634 	assert(__param < _M_num_parameters);
635 
636 	// '.' separates the parameter number from the field
637 	// name, if there is one.
638 	++__start;
639 	if (*__start != '.')
640 	  {
641 	    assert(*__start == ';');
642 	    ++__start;
643 	    __buf[0] = '\0';
644 	    if (_M_parameters[__param]._M_kind == _Parameter::__integer)
645 	      {
646 		_M_format_word(__buf, __bufsize, "%ld",
647 			       _M_parameters[__param]._M_variant._M_integer._M_value);
648 		_M_print_word(__buf);
649 	      }
650 	    else if (_M_parameters[__param]._M_kind == _Parameter::__string)
651 	      _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
652 	    continue;
653 	  }
654 
655 	// Extract the field name we want
656 	enum { __max_field_len = 16 };
657 	char __field[__max_field_len];
658 	int __field_idx = 0;
659 	++__start;
660 	while (*__start != ';')
661 	  {
662 	    assert(*__start);
663 	    assert(__field_idx < __max_field_len-1);
664 	    __field[__field_idx++] = *__start++;
665 	  }
666 	++__start;
667 	__field[__field_idx] = 0;
668 
669 	_M_parameters[__param]._M_print_field(this, __field);
670       }
671   }
672 
673   // Instantiations.
674   template
675     void
676     _Error_formatter::_M_format_word(char*, int, const char*,
677 				     const void*) const;
678 
679   template
680     void
681     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
682 
683   template
684     void
685     _Error_formatter::_M_format_word(char*, int, const char*,
686 				     std::size_t) const;
687 
688   template
689     void
690     _Error_formatter::_M_format_word(char*, int, const char*,
691 				     const char*) const;
692 } // namespace __gnu_debug
693