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