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