xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/src/c++11/debug.cc (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1 // Debugging mode support code -*- C++ -*-
2 
3 // Copyright (C) 2003-2022 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 #include <bits/move.h>
26 #include <bits/stl_iterator_base_types.h>
27 
28 #include <debug/formatter.h>
29 #include <debug/safe_base.h>
30 #include <debug/safe_unordered_base.h>
31 #include <debug/safe_iterator.h>
32 #include <debug/safe_local_iterator.h>
33 #include <debug/vector>
34 
35 #include <cassert>
36 #include <cstdio>	// for std::fprintf, stderr
37 #include <cstdlib>	// for std::abort
38 #include <cctype>	// for std::isspace.
39 #include <cstring>	// for std::strstr.
40 
41 #include <algorithm>	// for std::min.
42 
43 #include <cxxabi.h>	// for __cxa_demangle.
44 
45 #include "mutex_pool.h"
46 
47 #ifdef _GLIBCXX_VERBOSE_ASSERT
48 namespace std
49 {
50   [[__noreturn__]]
51   void
52   __glibcxx_assert_fail(const char* file, int line,
53 			const char* function, const char* condition) noexcept
54   {
55     if (file && function && condition)
56       fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.\n",
57 	      file, line, function, condition);
58     else if (function)
59       fprintf(stderr, "%s: Undefined behavior detected.\n", function);
60     abort();
61   }
62 }
63 #endif
64 
65 using namespace std;
66 
67 namespace
68 {
69   /** Returns different instances of __mutex depending on the passed address
70    *  in order to limit contention without breaking current library binary
71    *  compatibility. */
72   __gnu_cxx::__mutex&
73   get_safe_base_mutex(void* address)
74   {
75     // Use arbitrarily __gnu_debug::vector<int> as the container giving
76     // alignment of debug containers.
77     const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector<int>));
78     const unsigned char index
79       = (reinterpret_cast<std::size_t>(address) >> alignbits)
80       & __gnu_internal::mask;
81     return __gnu_internal::get_mutex(index);
82   }
83 
84 #pragma GCC diagnostic push
85 // Suppress -Wabi=2 warnings due to PR c++/51322 mangling change
86 #pragma GCC diagnostic warning "-Wabi=6"
87 
88   void
89   swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
90 	   __gnu_debug::_Safe_iterator_base*& __lhs_its,
91 	   __gnu_debug::_Safe_sequence_base& __rhs,
92 	   __gnu_debug::_Safe_iterator_base*& __rhs_its)
93   {
94     swap(__lhs_its, __rhs_its);
95     __gnu_debug::_Safe_iterator_base* __iter;
96     for (__iter = __rhs_its; __iter; __iter = __iter->_M_next)
97       __iter->_M_sequence = &__rhs;
98     for (__iter = __lhs_its; __iter; __iter = __iter->_M_next)
99       __iter->_M_sequence = &__lhs;
100   }
101 
102   void
103   swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
104 		  __gnu_debug::_Safe_sequence_base& __rhs)
105   {
106     swap(__lhs._M_version, __rhs._M_version);
107     swap_its(__lhs, __lhs._M_iterators,
108 	     __rhs, __rhs._M_iterators);
109     swap_its(__lhs, __lhs._M_const_iterators,
110 	     __rhs, __rhs._M_const_iterators);
111   }
112 #pragma GCC diagnostic pop
113 
114   template<typename _Action>
115     void
116     lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex,
117 		 _Action action)
118     {
119       // We need to lock both sequences to run action.
120       if (&lhs_mutex == &rhs_mutex)
121 	{
122 	  __gnu_cxx::__scoped_lock sentry(lhs_mutex);
123 	  action();
124 	}
125       else
126 	{
127 	  __gnu_cxx::__scoped_lock sentry1(&lhs_mutex < &rhs_mutex
128 					   ? lhs_mutex : rhs_mutex);
129 	  __gnu_cxx::__scoped_lock sentry2(&lhs_mutex < &rhs_mutex
130 					   ? rhs_mutex : lhs_mutex);
131 	  action();
132 	}
133     }
134 
135   void
136   swap_seq(__gnu_cxx::__mutex& lhs_mutex,
137 	   __gnu_debug::_Safe_sequence_base& lhs,
138 	   __gnu_cxx::__mutex& rhs_mutex,
139 	   __gnu_debug::_Safe_sequence_base& rhs)
140   {
141     lock_and_run(lhs_mutex, rhs_mutex,
142 		 [&lhs, &rhs]() { swap_seq_single(lhs, rhs); });
143   }
144 
145   void
146   swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs,
147 		    __gnu_debug::_Safe_unordered_container_base& __rhs)
148   {
149     swap_seq_single(__lhs, __rhs);
150     swap_its(__lhs, __lhs._M_local_iterators,
151 	     __rhs, __rhs._M_local_iterators);
152     swap_its(__lhs, __lhs._M_const_local_iterators,
153 	     __rhs, __rhs._M_const_local_iterators);
154   }
155 
156   void
157   swap_ucont(__gnu_cxx::__mutex& lhs_mutex,
158 	     __gnu_debug::_Safe_unordered_container_base& lhs,
159 	     __gnu_cxx::__mutex& rhs_mutex,
160 	     __gnu_debug::_Safe_unordered_container_base& rhs)
161   {
162     lock_and_run(lhs_mutex, rhs_mutex,
163 		 [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); });
164   }
165 
166   void
167   detach_all(__gnu_debug::_Safe_iterator_base* __iter)
168   {
169     for (; __iter;)
170       {
171 	__gnu_debug::_Safe_iterator_base* __old = __iter;
172 	__iter = __iter->_M_next;
173 	__old->_M_reset();
174       }
175   }
176 } // anonymous namespace
177 
178 namespace __gnu_debug
179 {
180   const char* const _S_debug_messages[] =
181   {
182     // General Checks
183     "function requires a valid iterator range [%1.name;, %2.name;)",
184     "attempt to insert into container with a singular iterator",
185     "attempt to insert into container with an iterator"
186     " from a different container",
187     "attempt to erase from container with a %2.state; iterator",
188     "attempt to erase from container with an iterator"
189     " from a different container",
190     "attempt to subscript container with out-of-bounds index %2;,"
191     " but container only holds %3; elements",
192     "attempt to access an element in an empty container",
193     "elements in iterator range [%1.name;, %2.name;)"
194     " are not partitioned by the value %3;",
195     "elements in iterator range [%1.name;, %2.name;)"
196     " are not partitioned by the predicate %3; and value %4;",
197     "elements in iterator range [%1.name;, %2.name;) are not sorted",
198     "elements in iterator range [%1.name;, %2.name;)"
199     " are not sorted according to the predicate %3;",
200     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
201     "elements in iterator range [%1.name;, %2.name;)"
202     " do not form a heap with respect to the predicate %3;",
203     // std::bitset checks
204     "attempt to write through a singular bitset reference",
205     "attempt to read from a singular bitset reference",
206     "attempt to flip a singular bitset reference",
207     // std::list checks
208     "attempt to splice a list into itself",
209     "attempt to splice lists with unequal allocators",
210     "attempt to splice elements referenced by a %1.state; iterator",
211     "attempt to splice an iterator from a different container",
212     "splice destination %1.name;"
213     " occurs within source range [%2.name;, %3.name;)",
214     // iterator checks
215     "attempt to initialize an iterator that will immediately become singular",
216     "attempt to copy-construct an iterator from a singular iterator",
217     "attempt to construct a constant iterator"
218     " from a singular mutable iterator",
219     "attempt to copy from a singular iterator",
220     "attempt to dereference a %1.state; iterator",
221     "attempt to increment a %1.state; iterator",
222     "attempt to decrement a %1.state; iterator",
223     "attempt to subscript a %1.state; iterator %2; step from"
224     " its current position, which falls outside its dereferenceable range",
225     "attempt to advance a %1.state; iterator %2; steps,"
226     " which falls outside its valid range",
227     "attempt to retreat a %1.state; iterator %2; steps,"
228     " which falls outside its valid range",
229     "attempt to compare a %1.state; iterator to a %2.state; iterator",
230     "attempt to compare iterators from different sequences",
231     "attempt to order a %1.state; iterator to a %2.state; iterator",
232     "attempt to order iterators from different sequences",
233     "attempt to compute the difference between a %1.state;"
234     " iterator to a %2.state; iterator",
235     "attempt to compute the different between two iterators"
236     " from different sequences",
237     // istream_iterator
238     "attempt to dereference an end-of-stream istream_iterator",
239     "attempt to increment an end-of-stream istream_iterator",
240     // ostream_iterator
241     "attempt to output via an ostream_iterator with no associated stream",
242     // istreambuf_iterator
243     "attempt to dereference an end-of-stream istreambuf_iterator"
244     " (this is a GNU extension)",
245     "attempt to increment an end-of-stream istreambuf_iterator",
246     // std::forward_list
247     "attempt to insert into container after an end iterator",
248     "attempt to erase from container after a %2.state; iterator not followed"
249     " by a dereferenceable one",
250     "function requires a valid iterator range (%2.name;, %3.name;)"
251     ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
252     // std::unordered_container::local_iterator
253     "attempt to compare local iterators from different unordered container"
254     " buckets",
255     "function requires a non-empty iterator range [%1.name;, %2.name;)",
256     "attempt to self move assign",
257     "attempt to access container with out-of-bounds bucket index %2;,"
258     " container only holds %3; buckets",
259     "load factor shall be positive",
260     "allocators must be equal",
261     "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
262     " container",
263     "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
264   };
265 
266   void
267   _Safe_sequence_base::
268   _M_detach_all()
269   {
270     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
271     detach_all(_M_iterators);
272     _M_iterators = 0;
273 
274     detach_all(_M_const_iterators);
275     _M_const_iterators = 0;
276   }
277 
278   void
279   _Safe_sequence_base::
280   _M_detach_singular()
281   {
282     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
283     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
284       {
285 	_Safe_iterator_base* __old = __iter;
286 	__iter = __iter->_M_next;
287 	if (__old->_M_singular())
288 	  __old->_M_detach_single();
289       }
290 
291     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
292       {
293 	_Safe_iterator_base* __old = __iter2;
294 	__iter2 = __iter2->_M_next;
295 	if (__old->_M_singular())
296 	  __old->_M_detach_single();
297       }
298   }
299 
300   void
301   _Safe_sequence_base::
302   _M_revalidate_singular()
303   {
304     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
305     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
306 	 __iter = __iter->_M_next)
307       __iter->_M_version = _M_version;
308 
309     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
310 	 __iter2 = __iter2->_M_next)
311       __iter2->_M_version = _M_version;
312   }
313 
314   void
315   _Safe_sequence_base::
316   _M_swap(_Safe_sequence_base& __x) noexcept
317   { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
318 
319   __gnu_cxx::__mutex&
320   _Safe_sequence_base::
321   _M_get_mutex() throw ()
322   { return get_safe_base_mutex(this); }
323 
324   void
325   _Safe_sequence_base::
326   _M_attach(_Safe_iterator_base* __it, bool __constant)
327   {
328     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
329     _M_attach_single(__it, __constant);
330   }
331 
332   void
333   _Safe_sequence_base::
334   _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
335   {
336     _Safe_iterator_base*& __its =
337       __constant ? _M_const_iterators : _M_iterators;
338     __it->_M_next = __its;
339     if (__it->_M_next)
340       __it->_M_next->_M_prior = __it;
341     __its = __it;
342   }
343 
344   void
345   _Safe_sequence_base::
346   _M_detach(_Safe_iterator_base* __it)
347   {
348     // Remove __it from this sequence's list
349     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
350     _M_detach_single(__it);
351   }
352 
353   void
354   _Safe_sequence_base::
355   _M_detach_single(_Safe_iterator_base* __it) throw ()
356   {
357     // Remove __it from this sequence's list
358     __it->_M_unlink();
359     if (_M_const_iterators == __it)
360       _M_const_iterators = __it->_M_next;
361     if (_M_iterators == __it)
362       _M_iterators = __it->_M_next;
363   }
364 
365   void
366   _Safe_iterator_base::
367   _M_attach(_Safe_sequence_base* __seq, bool __constant)
368   {
369     _M_detach();
370 
371     // Attach to the new sequence (if there is one)
372     if (__seq)
373       {
374 	_M_sequence = __seq;
375 	_M_version = _M_sequence->_M_version;
376 	_M_sequence->_M_attach(this, __constant);
377       }
378   }
379 
380   void
381   _Safe_iterator_base::
382   _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
383   {
384     _M_detach_single();
385 
386     // Attach to the new sequence (if there is one)
387     if (__seq)
388       {
389 	_M_sequence = __seq;
390 	_M_version = _M_sequence->_M_version;
391 	_M_sequence->_M_attach_single(this, __constant);
392       }
393   }
394 
395   void
396   _Safe_iterator_base::
397   _M_detach()
398   {
399     // This function can run concurrently with the sequence destructor,
400     // so there is a TOCTTOU race here: the sequence could be destroyed
401     // after we check that _M_sequence is not null. Use the pointer value
402     // to acquire the mutex (rather than via _M_sequence->_M_get_mutex()).
403     // If the sequence destructor runs between loading the pointer and
404     // locking the mutex, it will detach this iterator and set _M_sequence
405     // to null, and then _M_detach_single() will do nothing.
406     if (auto seq = __atomic_load_n(&_M_sequence, __ATOMIC_ACQUIRE))
407       {
408 	__gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq));
409 	_M_detach_single();
410       }
411   }
412 
413   void
414   _Safe_iterator_base::
415   _M_detach_single() throw ()
416   {
417     if (_M_sequence)
418       {
419 	_M_sequence->_M_detach_single(this);
420 	_M_reset();
421       }
422   }
423 
424   void
425   _Safe_iterator_base::
426   _M_reset() throw ()
427   {
428     __atomic_store_n(&_M_sequence, (_Safe_sequence_base*)0, __ATOMIC_RELEASE);
429     _M_version = 0;
430     _M_prior = 0;
431     _M_next = 0;
432   }
433 
434   bool
435   _Safe_iterator_base::
436   _M_singular() const throw ()
437   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
438 
439   bool
440   _Safe_iterator_base::
441   _M_can_compare(const _Safe_iterator_base& __x) const throw ()
442   { return _M_sequence == __x._M_sequence; }
443 
444   __gnu_cxx::__mutex&
445   _Safe_iterator_base::
446   _M_get_mutex() throw ()
447   { return _M_sequence->_M_get_mutex(); }
448 
449   _Safe_unordered_container_base*
450   _Safe_local_iterator_base::
451   _M_get_container() const noexcept
452   { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
453 
454   void
455   _Safe_local_iterator_base::
456   _M_attach(_Safe_sequence_base* __cont, bool __constant)
457   {
458     _M_detach();
459 
460     // Attach to the new container (if there is one)
461     if (__cont)
462       {
463 	_M_sequence = __cont;
464 	_M_version = _M_sequence->_M_version;
465 	_M_get_container()->_M_attach_local(this, __constant);
466       }
467   }
468 
469   void
470   _Safe_local_iterator_base::
471   _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
472   {
473     _M_detach_single();
474 
475     // Attach to the new container (if there is one)
476     if (__cont)
477       {
478 	_M_sequence = __cont;
479 	_M_version = _M_sequence->_M_version;
480 	_M_get_container()->_M_attach_local_single(this, __constant);
481       }
482   }
483 
484   void
485   _Safe_local_iterator_base::
486   _M_detach()
487   {
488     if (auto seq = __atomic_load_n(&_M_sequence, __ATOMIC_ACQUIRE))
489       {
490 	__gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq));
491 	_M_detach_single();
492       }
493   }
494 
495   void
496   _Safe_local_iterator_base::
497   _M_detach_single() throw ()
498   {
499     if (_M_sequence)
500       {
501 	_M_get_container()->_M_detach_local_single(this);
502 	_M_reset();
503       }
504   }
505 
506   void
507   _Safe_unordered_container_base::
508   _M_detach_all()
509   {
510     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
511     detach_all(_M_iterators);
512     _M_iterators = 0;
513 
514     detach_all(_M_const_iterators);
515     _M_const_iterators = 0;
516 
517     detach_all(_M_local_iterators);
518     _M_local_iterators = 0;
519 
520     detach_all(_M_const_local_iterators);
521     _M_const_local_iterators = 0;
522   }
523 
524   void
525   _Safe_unordered_container_base::
526   _M_swap(_Safe_unordered_container_base& __x) noexcept
527   { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
528 
529   void
530   _Safe_unordered_container_base::
531   _M_attach_local(_Safe_iterator_base* __it, bool __constant)
532   {
533     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
534     _M_attach_local_single(__it, __constant);
535   }
536 
537   void
538   _Safe_unordered_container_base::
539   _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
540   {
541     _Safe_iterator_base*& __its =
542       __constant ? _M_const_local_iterators : _M_local_iterators;
543     __it->_M_next = __its;
544     if (__it->_M_next)
545       __it->_M_next->_M_prior = __it;
546     __its = __it;
547   }
548 
549   void
550   _Safe_unordered_container_base::
551   _M_detach_local(_Safe_iterator_base* __it)
552   {
553     // Remove __it from this container's list
554     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
555     _M_detach_local_single(__it);
556   }
557 
558   void
559   _Safe_unordered_container_base::
560   _M_detach_local_single(_Safe_iterator_base* __it) throw ()
561   {
562     // Remove __it from this container's list
563     __it->_M_unlink();
564     if (_M_const_local_iterators == __it)
565       _M_const_local_iterators = __it->_M_next;
566     if (_M_local_iterators == __it)
567       _M_local_iterators = __it->_M_next;
568   }
569 }
570 
571 namespace
572 {
573   using _Error_formatter = __gnu_debug::_Error_formatter;
574   using _Parameter = __gnu_debug::_Error_formatter::_Parameter;
575 
576   void
577   get_max_length(std::size_t& max_length)
578   {
579     const char* nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
580     if (nptr)
581       {
582 	char* endptr;
583 	const unsigned long ret = std::strtoul(nptr, &endptr, 0);
584 	if (*nptr != '\0' && *endptr == '\0')
585 	  max_length = ret;
586       }
587   }
588 
589   struct PrintContext
590   {
591     PrintContext()
592     : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
593     { get_max_length(_M_max_length); }
594 
595     static constexpr int _S_indent = 4;
596     std::size_t	_M_max_length;
597     std::size_t	_M_column;
598     bool	_M_first_line;
599     bool	_M_wordwrap;
600   };
601 
602   using _Print_func_t = void (PrintContext&, const char*, ptrdiff_t);
603 
604   template<size_t Length>
605     void
606     print_literal(PrintContext& ctx, const char(&word)[Length])
607     { print_word(ctx, word, Length - 1); }
608 
609   void
610   print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1)
611   {
612     if (nbc >= 0)
613       ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str);
614     else
615       ctx._M_column += fprintf(stderr, "%s", str);
616   }
617 
618   void
619   print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
620   {
621     size_t length = nbc >= 0 ? nbc : __builtin_strlen(word);
622     if (length == 0)
623       return;
624 
625     // First consider '\n' at the beginning because it impacts the column.
626     if (word[0] == '\n')
627       {
628 	fprintf(stderr, "\n");
629 	ctx._M_column = 1;
630 	++word;
631 	--length;
632 
633 	if (length == 0)
634 	  return;
635       }
636 
637     size_t visual_length
638       = isspace((unsigned char)word[length - 1]) ? length - 1 : length;
639     if (visual_length == 0
640 	|| !ctx._M_wordwrap
641 	|| (ctx._M_column + visual_length < ctx._M_max_length)
642 	|| (visual_length >= ctx._M_max_length && ctx._M_column == 1))
643       {
644 	// If this isn't the first line, indent
645 	if (ctx._M_column == 1 && !ctx._M_first_line)
646 	  {
647 	    const char spacing[PrintContext::_S_indent + 1] = "    ";
648 	    print_raw(ctx, spacing, PrintContext::_S_indent);
649 	  }
650 
651 	int written = fprintf(stderr, "%.*s", (int)length, word);
652 
653 	if (word[length - 1] == '\n')
654 	  {
655 	    ctx._M_first_line = false;
656 	    ctx._M_column = 1;
657 	  }
658 	else
659 	  ctx._M_column += written;
660       }
661     else
662       {
663 	print_literal(ctx, "\n");
664 	print_word(ctx, word, nbc);
665       }
666   }
667 
668   void
669   pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func)
670   {
671     const char cxx1998[] = "cxx1998::";
672     for (;;)
673       {
674 	if (auto pos = strstr(str, "__"))
675 	  {
676 	    if (pos != str)
677 	      print_func(ctx, str, pos - str);
678 
679 	    pos += 2; // advance past "__"
680 	    if (memcmp(pos, cxx1998, 9) == 0)
681 	      pos += 9; // advance part "cxx1998::"
682 
683 	    str = pos;
684 	  }
685 	else
686 	  {
687 	    print_func(ctx, str, -1);
688 	    break;
689 	  }
690       }
691   }
692 
693   template<size_t Length>
694     void
695     print_type_info(PrintContext& ctx,
696 		    const type_info* info,
697 		    const char(&unknown_name)[Length])
698     {
699       if (!info)
700 	print_literal(ctx, unknown_name);
701       else
702 	{
703 	  int status;
704 	  char* demangled_name =
705 	    __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status);
706 	  if (status == 0)
707 	    pretty_print(ctx, demangled_name, &print_word);
708 	  else
709 	    print_word(ctx, info->name());
710 	  free(demangled_name);
711 	}
712     }
713 
714   void
715   print_address(PrintContext& ctx, const char* fmt, const void* address)
716   {
717     char buf[128];
718     int written = __builtin_sprintf(buf, fmt, address);
719     print_word(ctx, buf, written);
720   }
721 
722   void
723   print_address(PrintContext& ctx, const void* address)
724   { print_address(ctx, "%p", address); }
725 
726   void
727   print_integer(PrintContext& ctx, long integer)
728   {
729     char buf[64];
730     int written = __builtin_sprintf(buf, "%ld", integer);
731     print_word(ctx, buf, written);
732   }
733 
734   void
735   print_named_name(PrintContext& ctx, const _Parameter::_Named& named)
736   {
737     assert(named._M_name);
738     pretty_print(ctx, named._M_name, print_word);
739   }
740 
741   template<typename _Iterator>
742     void
743     print_iterator_constness(PrintContext& ctx, const _Iterator& iterator)
744     {
745       static const char*
746 	constness_names[_Error_formatter::__last_constness] =
747 	{
748 	 "<unknown constness>",
749 	 "constant",
750 	 "mutable"
751 	};
752       print_word(ctx, constness_names[iterator._M_constness]);
753     }
754 
755   template<typename _Iterator>
756     void
757     print_iterator_state(PrintContext& ctx, const _Iterator& iterator)
758     {
759       static const char*
760 	state_names[_Error_formatter::__last_state] =
761 	{
762 	 "<unknown state>",
763 	 "singular",
764 	 "dereferenceable (start-of-sequence)",
765 	 "dereferenceable",
766 	 "past-the-end",
767 	 "before-begin",
768 	 "dereferenceable (start-of-reverse-sequence)",
769 	 "dereferenceable (reverse)",
770 	 "past-the-reverse-end"
771 	};
772       print_word(ctx, state_names[iterator._M_state]);
773     }
774 
775   template<typename _Iterator>
776     void
777     print_iterator_seq_type(PrintContext& ctx, const _Iterator& iterator)
778     { print_type_info(ctx, iterator._M_seq_type, "<unknown seq_type>"); }
779 
780   bool
781   print_named_field(PrintContext& ctx,
782 		    const char* fname, const _Parameter::_Named& named)
783   {
784     if (__builtin_strcmp(fname, "name") == 0)
785       print_named_name(ctx, named);
786     else
787       return false;
788 
789     return true;
790   }
791 
792   bool
793   print_type_field(PrintContext& ctx,
794 		   const char* fname, const _Parameter::_Type& type)
795   {
796     if (print_named_field(ctx, fname, type))
797       { }
798     else if (__builtin_strcmp(fname, "type") == 0)
799       print_type_info(ctx, type._M_type, "<unknown type>");
800     else
801       return false;
802 
803     return true;
804   }
805 
806   bool
807   print_instance_field(PrintContext& ctx,
808 		       const char* fname, const _Parameter::_Instance& inst)
809   {
810     if (print_type_field(ctx, fname, inst))
811       { }
812     else if (__builtin_strcmp(fname, "address") == 0)
813       print_address(ctx, inst._M_address);
814     else
815       return false;
816 
817     return true;
818   }
819 
820   template<typename _Iterator>
821     bool
822     print_iterator_field(PrintContext& ctx,
823 			 const char* fname, const _Iterator& iterator)
824     {
825       if (print_instance_field(ctx, fname, iterator))
826 	{ }
827       else if (__builtin_strcmp(fname, "constness") == 0)
828 	print_iterator_constness(ctx, iterator);
829       else if (__builtin_strcmp(fname, "state") == 0)
830 	print_iterator_state(ctx, iterator);
831       else if (__builtin_strcmp(fname, "sequence") == 0)
832 	{
833 	  assert(iterator._M_sequence);
834 	  print_address(ctx, iterator._M_sequence);
835 	}
836       else if (__builtin_strcmp(fname, "seq_type") == 0)
837 	print_iterator_seq_type(ctx, iterator);
838       else
839 	return false;
840 
841       return true;
842     }
843 
844   void
845   print_field(PrintContext& ctx, const _Parameter& param, const char* fname)
846   {
847     assert(param._M_kind != _Parameter::__unused_param);
848 
849     const auto& variant = param._M_variant;
850     switch (param._M_kind)
851     {
852     case _Parameter::__iterator:
853       if (!print_iterator_field(ctx, fname, variant._M_iterator))
854 	assert(false);
855       break;
856 
857     case _Parameter::__sequence:
858       if (!print_instance_field(ctx, fname, variant._M_sequence))
859 	assert(false);
860       break;
861 
862     case _Parameter::__integer:
863       if (!print_named_field(ctx, fname, variant._M_integer))
864 	assert(false);
865       break;
866 
867     case _Parameter::__string:
868       if (!print_named_field(ctx, fname, variant._M_string))
869 	assert(false);
870       break;
871 
872     case _Parameter::__instance:
873       if (!print_instance_field(ctx, fname, variant._M_instance))
874 	assert(false);
875       break;
876 
877     case _Parameter::__iterator_value_type:
878       if (!print_type_field(ctx, fname, variant._M_iterator_value_type))
879 	assert(false);
880       break;
881 
882     default:
883       assert(false);
884       break;
885     }
886   }
887 
888   void
889   print_quoted_named_name(PrintContext& ctx, const _Parameter::_Named& named)
890   {
891     if (named._M_name)
892       {
893 	print_literal(ctx, "\"");
894 	print_named_name(ctx, named);
895 	print_literal(ctx, "\" ");
896       }
897   }
898 
899   void
900   print_type_type(PrintContext& ctx, const _Parameter::_Type& type,
901 		  bool close_desc = true)
902   {
903     if (type._M_type)
904       {
905 	print_literal(ctx, "  type = ");
906 	print_type_info(ctx, type._M_type, "<unknown type>");
907 	if (close_desc)
908 	  print_literal(ctx, ";\n");
909       }
910   }
911 
912   void
913   print_type(PrintContext& ctx, const _Parameter::_Type& type)
914   {
915     print_quoted_named_name(ctx, type);
916     print_literal(ctx, " {\n");
917     print_type_type(ctx, type);
918     print_literal(ctx, "}\n");
919   }
920 
921   void
922   print_instance(PrintContext& ctx, const _Parameter::_Instance& inst,
923 		 bool close_desc = true)
924   {
925     print_quoted_named_name(ctx, inst);
926     print_address(ctx, "@ %p {\n", inst._M_address);
927     print_type_type(ctx, inst, close_desc);
928 
929     if (close_desc)
930       print_literal(ctx, "}\n");
931   }
932 
933   void
934   print_description(PrintContext& ctx, const _Parameter& param)
935   {
936     const auto& variant = param._M_variant;
937     switch (param._M_kind)
938       {
939       case _Parameter::__iterator:
940 	{
941 	  const auto& ite = variant._M_iterator;
942 
943 	  print_literal(ctx, "iterator ");
944 	  print_instance(ctx, ite, false);
945 
946 	  if (ite._M_type)
947 	    {
948 	      if (ite._M_constness != _Error_formatter::__unknown_constness)
949 		{
950 		  print_literal(ctx, " (");
951 		  print_iterator_constness(ctx, ite);
952 		  print_literal(ctx, " iterator)");
953 		}
954 
955 	      print_literal(ctx, ";\n");
956 	    }
957 
958 	  if (ite._M_state != _Error_formatter::__unknown_state)
959 	    {
960 	      print_literal(ctx, "  state = ");
961 	      print_iterator_state(ctx, ite);
962 	      print_literal(ctx, ";\n");
963 	    }
964 
965 	  if (ite._M_sequence)
966 	    {
967 	      print_literal(ctx, "  references sequence ");
968 	      if (ite._M_seq_type)
969 		{
970 		  print_literal(ctx, "with type '");
971 		  print_iterator_seq_type(ctx, ite);
972 		  print_literal(ctx, "' ");
973 		}
974 
975 	      print_address(ctx, "@ %p\n", ite._M_sequence);
976 	    }
977 
978 	  print_literal(ctx, "}\n");
979 	}
980 	break;
981 
982       case _Parameter::__sequence:
983 	print_literal(ctx, "sequence ");
984 	print_instance(ctx, variant._M_sequence);
985 	break;
986 
987       case _Parameter::__instance:
988 	print_literal(ctx, "instance ");
989 	print_instance(ctx, variant._M_instance);
990 	break;
991 
992       case _Parameter::__iterator_value_type:
993 	print_literal(ctx, "iterator::value_type ");
994 	print_type(ctx, variant._M_iterator_value_type);
995 	break;
996 
997       default:
998 	break;
999       }
1000   }
1001 
1002   void
1003   print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc,
1004 	       const _Parameter* parameters, std::size_t num_parameters)
1005   {
1006     const char* start = str;
1007     const char* end = nbc >= 0 ? start + nbc : nullptr;
1008 
1009     while ((end && str != end) || (!end && *str))
1010       {
1011 	if (isspace((unsigned char)*str))
1012 	  {
1013 	    ++str;
1014 	    print_word(ctx, start, str - start);
1015 	    start = str;
1016 	    continue;
1017 	  }
1018 
1019 	if (!parameters || *str != '%')
1020 	  {
1021 	    // Normal char or no parameter to look for.
1022 	    ++str;
1023 	    continue;
1024 	  }
1025 
1026 	if (*++str == '%')
1027 	  {
1028 	    // Escaped '%'
1029 	    print_word(ctx, start, str - start);
1030 	    ++str;
1031 	    start = str;
1032 	    continue;
1033 	  }
1034 
1035 	// We are on a parameter property reference, we need to flush buffer
1036 	// first.
1037 	if (str != start)
1038 	  {
1039 	    // Avoid printing the '%'.
1040 	    if (str - start > 1)
1041 	      print_word(ctx, start, str - start - 1);
1042 	    start = str;
1043 	  }
1044 
1045 	// Get the parameter number
1046 	assert(*str >= '1' && *str <= '9');
1047 	size_t param_index = *str - '0' - 1;
1048 	assert(param_index < num_parameters);
1049 	const auto& param = parameters[param_index];
1050 
1051 	// '.' separates the parameter number from the field
1052 	// name, if there is one.
1053 	++str;
1054 	if (*str != '.')
1055 	  {
1056 	    assert(*str == ';');
1057 	    ++str;
1058 	    if (param._M_kind == _Parameter::__integer)
1059 	      print_integer(ctx, param._M_variant._M_integer._M_value);
1060 	    else if (param._M_kind == _Parameter::__string)
1061 	      print_string(ctx, param._M_variant._M_string._M_value, -1,
1062 			   parameters, num_parameters);
1063 	    start = str;
1064 	    continue;
1065 	  }
1066 
1067 	// Extract the field name we want
1068 	const int max_field_len = 16;
1069 	char field[max_field_len];
1070 	int field_idx = 0;
1071 	++str;
1072 	while (*str != ';')
1073 	  {
1074 	    assert(*str);
1075 	    assert(field_idx < max_field_len - 1);
1076 	    field[field_idx++] = *str++;
1077 	  }
1078 	++str;
1079 	field[field_idx] = '\0';
1080 
1081 	print_field(ctx, param, field);
1082 	start = str;
1083       }
1084 
1085     // Might need to flush.
1086     if (str != start)
1087       print_word(ctx, start, str - start);
1088   }
1089 
1090   void
1091   print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc)
1092   { print_string(ctx, str, nbc, nullptr, 0); }
1093 }
1094 
1095 namespace __gnu_debug
1096 {
1097   _Error_formatter&
1098   _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
1099   {
1100     return const_cast<_Error_formatter*>(this)
1101       ->_M_message(_S_debug_messages[__id]);
1102   }
1103 
1104   void
1105   _Error_formatter::_M_error() const
1106   {
1107     // Emit file & line number information
1108     bool go_to_next_line = false;
1109     PrintContext ctx;
1110     if (_M_file)
1111       {
1112 	print_raw(ctx, _M_file);
1113 	print_literal(ctx, ":");
1114 	go_to_next_line = true;
1115       }
1116 
1117     if (_M_line > 0)
1118       {
1119 	ctx._M_column += fprintf(stderr, "%u", _M_line);
1120 	print_literal(ctx, ":");
1121 	go_to_next_line = true;
1122       }
1123 
1124     if (go_to_next_line)
1125       print_literal(ctx, "\n");
1126 
1127     if (ctx._M_max_length)
1128       ctx._M_wordwrap = true;
1129 
1130     if (_M_function)
1131       {
1132 	print_literal(ctx, "In function:\n");
1133 	pretty_print(ctx, _M_function, &print_string);
1134 	print_literal(ctx, "\n");
1135 	ctx._M_first_line = true;
1136 	print_literal(ctx, "\n");
1137       }
1138 
1139     print_literal(ctx, "Error: ");
1140 
1141     // Print the error message
1142     assert(_M_text);
1143     print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters);
1144     print_literal(ctx, ".\n");
1145 
1146     // Emit descriptions of the objects involved in the operation
1147     ctx._M_first_line = true;
1148     ctx._M_wordwrap = false;
1149     bool has_header = false;
1150     for (unsigned int i = 0; i < _M_num_parameters; ++i)
1151       {
1152 	switch (_M_parameters[i]._M_kind)
1153 	  {
1154 	  case _Parameter::__iterator:
1155 	  case _Parameter::__sequence:
1156 	  case _Parameter::__instance:
1157 	  case _Parameter::__iterator_value_type:
1158 	    if (!has_header)
1159 	      {
1160 		print_literal(ctx, "\nObjects involved in the operation:\n");
1161 		has_header = true;
1162 	      }
1163 	    print_description(ctx, _M_parameters[i]);
1164 	    break;
1165 
1166 	  default:
1167 	    break;
1168 	  }
1169       }
1170 
1171     abort();
1172   }
1173 
1174 #if !_GLIBCXX_INLINE_VERSION
1175   // Deprecated methods kept for backward compatibility.
1176   void
1177   _Error_formatter::_Parameter::_M_print_field(
1178 	const _Error_formatter*, const char*) const
1179   { }
1180 
1181   void
1182   _Error_formatter::_Parameter::_M_print_description(const _Error_formatter*) const
1183   { }
1184 
1185   template<typename _Tp>
1186     void
1187     _Error_formatter::_M_format_word(char*, int, const char*, _Tp)
1188     const throw ()
1189     { }
1190 
1191   void
1192   _Error_formatter::_M_print_word(const char*) const
1193   { }
1194 
1195   void
1196   _Error_formatter::_M_print_string(const char*) const
1197   { }
1198 
1199   void
1200   _Error_formatter::_M_get_max_length() const throw ()
1201   { }
1202 
1203   // Instantiations.
1204   template
1205     void
1206     _Error_formatter::_M_format_word(char*, int, const char*,
1207                                     const void*) const;
1208 
1209   template
1210     void
1211     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
1212 
1213   template
1214     void
1215     _Error_formatter::_M_format_word(char*, int, const char*,
1216                                     std::size_t) const;
1217 
1218   template
1219     void
1220     _Error_formatter::_M_format_word(char*, int, const char*,
1221                                     const char*) const;
1222 #endif
1223 
1224 } // namespace __gnu_debug
1225