OSDN Git Service

PR 43839
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / debug.cc
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
36 using namespace std;
37
38 namespace
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
48 namespace __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