PR libstdc++/86450 use -Wabi=2 and simplify -Werror use
[official-gcc.git] / libstdc++-v3 / src / c++11 / debug.cc
blob88fe889dd6afd6b07e41f74e94ca726485826671
1 // Debugging mode support code -*- C++ -*-
3 // Copyright (C) 2003-2018 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.
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.
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.
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/>.
25 #include <bits/move.h>
26 #include <bits/stl_iterator_base_types.h>
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>
35 #include <cassert>
36 #include <cstdio>
37 #include <cctype> // for std::isspace
39 #include <algorithm> // for std::min
41 #include <cxxabi.h> // for __cxa_demangle
43 // libstdc++/85768
44 #if 0 // defined _GLIBCXX_HAVE_EXECINFO_H
45 # include <execinfo.h> // for backtrace
46 #endif
48 #include "mutex_pool.h"
50 using namespace std;
52 namespace
54 /** Returns different instances of __mutex depending on the passed address
55 * in order to limit contention without breaking current library binary
56 * compatibility. */
57 __gnu_cxx::__mutex&
58 get_safe_base_mutex(void* address)
60 // Use arbitrarily __gnu_debug::vector<int> as the container giving
61 // alignment of debug containers.
62 const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector<int>));
63 const unsigned char index
64 = (reinterpret_cast<std::size_t>(address) >> alignbits)
65 & __gnu_internal::mask;
66 return __gnu_internal::get_mutex(index);
69 #pragma GCC diagnostic push
70 // Suppress -Wabi=2 warnings due to PR c++/51322 mangling change
71 #pragma GCC diagnostic warning "-Wabi=6"
73 void
74 swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
75 __gnu_debug::_Safe_iterator_base*& __lhs_its,
76 __gnu_debug::_Safe_sequence_base& __rhs,
77 __gnu_debug::_Safe_iterator_base*& __rhs_its)
79 swap(__lhs_its, __rhs_its);
80 __gnu_debug::_Safe_iterator_base* __iter;
81 for (__iter = __rhs_its; __iter; __iter = __iter->_M_next)
82 __iter->_M_sequence = &__rhs;
83 for (__iter = __lhs_its; __iter; __iter = __iter->_M_next)
84 __iter->_M_sequence = &__lhs;
87 void
88 swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
89 __gnu_debug::_Safe_sequence_base& __rhs)
91 swap(__lhs._M_version, __rhs._M_version);
92 swap_its(__lhs, __lhs._M_iterators,
93 __rhs, __rhs._M_iterators);
94 swap_its(__lhs, __lhs._M_const_iterators,
95 __rhs, __rhs._M_const_iterators);
97 #pragma GCC diagnostic pop
99 template<typename _Action>
100 void
101 lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex,
102 _Action action)
104 // We need to lock both sequences to run action.
105 if (&lhs_mutex == &rhs_mutex)
107 __gnu_cxx::__scoped_lock sentry(lhs_mutex);
108 action();
110 else
112 __gnu_cxx::__scoped_lock sentry1(&lhs_mutex < &rhs_mutex
113 ? lhs_mutex : rhs_mutex);
114 __gnu_cxx::__scoped_lock sentry2(&lhs_mutex < &rhs_mutex
115 ? rhs_mutex : lhs_mutex);
116 action();
120 void
121 swap_seq(__gnu_cxx::__mutex& lhs_mutex,
122 __gnu_debug::_Safe_sequence_base& lhs,
123 __gnu_cxx::__mutex& rhs_mutex,
124 __gnu_debug::_Safe_sequence_base& rhs)
126 lock_and_run(lhs_mutex, rhs_mutex,
127 [&lhs, &rhs]() { swap_seq_single(lhs, rhs); });
130 void
131 swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs,
132 __gnu_debug::_Safe_unordered_container_base& __rhs)
134 swap_seq_single(__lhs, __rhs);
135 swap_its(__lhs, __lhs._M_local_iterators,
136 __rhs, __rhs._M_local_iterators);
137 swap_its(__lhs, __lhs._M_const_local_iterators,
138 __rhs, __rhs._M_const_local_iterators);
141 void
142 swap_ucont(__gnu_cxx::__mutex& lhs_mutex,
143 __gnu_debug::_Safe_unordered_container_base& lhs,
144 __gnu_cxx::__mutex& rhs_mutex,
145 __gnu_debug::_Safe_unordered_container_base& rhs)
147 lock_and_run(lhs_mutex, rhs_mutex,
148 [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); });
151 void
152 detach_all(__gnu_debug::_Safe_iterator_base* __iter)
154 for (; __iter;)
156 __gnu_debug::_Safe_iterator_base* __old = __iter;
157 __iter = __iter->_M_next;
158 __old->_M_reset();
161 } // anonymous namespace
163 namespace __gnu_debug
165 const char* const _S_debug_messages[] =
167 // General Checks
168 "function requires a valid iterator range [%1.name;, %2.name;)",
169 "attempt to insert into container with a singular iterator",
170 "attempt to insert into container with an iterator"
171 " from a different container",
172 "attempt to erase from container with a %2.state; iterator",
173 "attempt to erase from container with an iterator"
174 " from a different container",
175 "attempt to subscript container with out-of-bounds index %2;,"
176 " but container only holds %3; elements",
177 "attempt to access an element in an empty container",
178 "elements in iterator range [%1.name;, %2.name;)"
179 " are not partitioned by the value %3;",
180 "elements in iterator range [%1.name;, %2.name;)"
181 " are not partitioned by the predicate %3; and value %4;",
182 "elements in iterator range [%1.name;, %2.name;) are not sorted",
183 "elements in iterator range [%1.name;, %2.name;)"
184 " are not sorted according to the predicate %3;",
185 "elements in iterator range [%1.name;, %2.name;) do not form a heap",
186 "elements in iterator range [%1.name;, %2.name;)"
187 " do not form a heap with respect to the predicate %3;",
188 // std::bitset checks
189 "attempt to write through a singular bitset reference",
190 "attempt to read from a singular bitset reference",
191 "attempt to flip a singular bitset reference",
192 // std::list checks
193 "attempt to splice a list into itself",
194 "attempt to splice lists with unequal allocators",
195 "attempt to splice elements referenced by a %1.state; iterator",
196 "attempt to splice an iterator from a different container",
197 "splice destination %1.name;"
198 " occurs within source range [%2.name;, %3.name;)",
199 // iterator checks
200 "attempt to initialize an iterator that will immediately become singular",
201 "attempt to copy-construct an iterator from a singular iterator",
202 "attempt to construct a constant iterator"
203 " from a singular mutable iterator",
204 "attempt to copy from a singular iterator",
205 "attempt to dereference a %1.state; iterator",
206 "attempt to increment a %1.state; iterator",
207 "attempt to decrement a %1.state; iterator",
208 "attempt to subscript a %1.state; iterator %2; step from"
209 " its current position, which falls outside its dereferenceable range",
210 "attempt to advance a %1.state; iterator %2; steps,"
211 " which falls outside its valid range",
212 "attempt to retreat a %1.state; iterator %2; steps,"
213 " which falls outside its valid range",
214 "attempt to compare a %1.state; iterator to a %2.state; iterator",
215 "attempt to compare iterators from different sequences",
216 "attempt to order a %1.state; iterator to a %2.state; iterator",
217 "attempt to order iterators from different sequences",
218 "attempt to compute the difference between a %1.state;"
219 " iterator to a %2.state; iterator",
220 "attempt to compute the different between two iterators"
221 " from different sequences",
222 // istream_iterator
223 "attempt to dereference an end-of-stream istream_iterator",
224 "attempt to increment an end-of-stream istream_iterator",
225 // ostream_iterator
226 "attempt to output via an ostream_iterator with no associated stream",
227 // istreambuf_iterator
228 "attempt to dereference an end-of-stream istreambuf_iterator"
229 " (this is a GNU extension)",
230 "attempt to increment an end-of-stream istreambuf_iterator",
231 // std::forward_list
232 "attempt to insert into container after an end iterator",
233 "attempt to erase from container after a %2.state; iterator not followed"
234 " by a dereferenceable one",
235 "function requires a valid iterator range (%2.name;, %3.name;)"
236 ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
237 // std::unordered_container::local_iterator
238 "attempt to compare local iterators from different unordered container"
239 " buckets",
240 "function requires a non-empty iterator range [%1.name;, %2.name;)",
241 "attempt to self move assign",
242 "attempt to access container with out-of-bounds bucket index %2;,"
243 " container only holds %3; buckets",
244 "load factor shall be positive",
245 "allocators must be equal",
246 "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
247 " container",
248 "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
251 void
252 _Safe_sequence_base::
253 _M_detach_all()
255 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
256 detach_all(_M_iterators);
257 _M_iterators = 0;
259 detach_all(_M_const_iterators);
260 _M_const_iterators = 0;
263 void
264 _Safe_sequence_base::
265 _M_detach_singular()
267 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
268 for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
270 _Safe_iterator_base* __old = __iter;
271 __iter = __iter->_M_next;
272 if (__old->_M_singular())
273 __old->_M_detach_single();
276 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
278 _Safe_iterator_base* __old = __iter2;
279 __iter2 = __iter2->_M_next;
280 if (__old->_M_singular())
281 __old->_M_detach_single();
285 void
286 _Safe_sequence_base::
287 _M_revalidate_singular()
289 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
290 for (_Safe_iterator_base* __iter = _M_iterators; __iter;
291 __iter = __iter->_M_next)
292 __iter->_M_version = _M_version;
294 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
295 __iter2 = __iter2->_M_next)
296 __iter2->_M_version = _M_version;
299 void
300 _Safe_sequence_base::
301 _M_swap(_Safe_sequence_base& __x) noexcept
302 { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
304 __gnu_cxx::__mutex&
305 _Safe_sequence_base::
306 _M_get_mutex() throw ()
307 { return get_safe_base_mutex(this); }
309 void
310 _Safe_sequence_base::
311 _M_attach(_Safe_iterator_base* __it, bool __constant)
313 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
314 _M_attach_single(__it, __constant);
317 void
318 _Safe_sequence_base::
319 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
321 _Safe_iterator_base*& __its =
322 __constant ? _M_const_iterators : _M_iterators;
323 __it->_M_next = __its;
324 if (__it->_M_next)
325 __it->_M_next->_M_prior = __it;
326 __its = __it;
329 void
330 _Safe_sequence_base::
331 _M_detach(_Safe_iterator_base* __it)
333 // Remove __it from this sequence's list
334 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
335 _M_detach_single(__it);
338 void
339 _Safe_sequence_base::
340 _M_detach_single(_Safe_iterator_base* __it) throw ()
342 // Remove __it from this sequence's list
343 __it->_M_unlink();
344 if (_M_const_iterators == __it)
345 _M_const_iterators = __it->_M_next;
346 if (_M_iterators == __it)
347 _M_iterators = __it->_M_next;
350 void
351 _Safe_iterator_base::
352 _M_attach(_Safe_sequence_base* __seq, bool __constant)
354 _M_detach();
356 // Attach to the new sequence (if there is one)
357 if (__seq)
359 _M_sequence = __seq;
360 _M_version = _M_sequence->_M_version;
361 _M_sequence->_M_attach(this, __constant);
365 void
366 _Safe_iterator_base::
367 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
369 _M_detach_single();
371 // Attach to the new sequence (if there is one)
372 if (__seq)
374 _M_sequence = __seq;
375 _M_version = _M_sequence->_M_version;
376 _M_sequence->_M_attach_single(this, __constant);
380 void
381 _Safe_iterator_base::
382 _M_detach()
384 if (_M_sequence)
386 _M_sequence->_M_detach(this);
387 _M_reset();
391 void
392 _Safe_iterator_base::
393 _M_detach_single() throw ()
395 if (_M_sequence)
397 _M_sequence->_M_detach_single(this);
398 _M_reset();
402 void
403 _Safe_iterator_base::
404 _M_reset() throw ()
406 _M_sequence = 0;
407 _M_version = 0;
408 _M_prior = 0;
409 _M_next = 0;
412 bool
413 _Safe_iterator_base::
414 _M_singular() const throw ()
415 { return !_M_sequence || _M_version != _M_sequence->_M_version; }
417 bool
418 _Safe_iterator_base::
419 _M_can_compare(const _Safe_iterator_base& __x) const throw ()
421 return (!_M_singular()
422 && !__x._M_singular() && _M_sequence == __x._M_sequence);
425 __gnu_cxx::__mutex&
426 _Safe_iterator_base::
427 _M_get_mutex() throw ()
428 { return _M_sequence->_M_get_mutex(); }
430 _Safe_unordered_container_base*
431 _Safe_local_iterator_base::
432 _M_get_container() const noexcept
433 { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
435 void
436 _Safe_local_iterator_base::
437 _M_attach(_Safe_sequence_base* __cont, bool __constant)
439 _M_detach();
441 // Attach to the new container (if there is one)
442 if (__cont)
444 _M_sequence = __cont;
445 _M_version = _M_sequence->_M_version;
446 _M_get_container()->_M_attach_local(this, __constant);
450 void
451 _Safe_local_iterator_base::
452 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
454 _M_detach_single();
456 // Attach to the new container (if there is one)
457 if (__cont)
459 _M_sequence = __cont;
460 _M_version = _M_sequence->_M_version;
461 _M_get_container()->_M_attach_local_single(this, __constant);
465 void
466 _Safe_local_iterator_base::
467 _M_detach()
469 if (_M_sequence)
471 _M_get_container()->_M_detach_local(this);
472 _M_reset();
476 void
477 _Safe_local_iterator_base::
478 _M_detach_single() throw ()
480 if (_M_sequence)
482 _M_get_container()->_M_detach_local_single(this);
483 _M_reset();
487 void
488 _Safe_unordered_container_base::
489 _M_detach_all()
491 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
492 detach_all(_M_iterators);
493 _M_iterators = 0;
495 detach_all(_M_const_iterators);
496 _M_const_iterators = 0;
498 detach_all(_M_local_iterators);
499 _M_local_iterators = 0;
501 detach_all(_M_const_local_iterators);
502 _M_const_local_iterators = 0;
505 void
506 _Safe_unordered_container_base::
507 _M_swap(_Safe_unordered_container_base& __x) noexcept
508 { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
510 void
511 _Safe_unordered_container_base::
512 _M_attach_local(_Safe_iterator_base* __it, bool __constant)
514 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
515 _M_attach_local_single(__it, __constant);
518 void
519 _Safe_unordered_container_base::
520 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
522 _Safe_iterator_base*& __its =
523 __constant ? _M_const_local_iterators : _M_local_iterators;
524 __it->_M_next = __its;
525 if (__it->_M_next)
526 __it->_M_next->_M_prior = __it;
527 __its = __it;
530 void
531 _Safe_unordered_container_base::
532 _M_detach_local(_Safe_iterator_base* __it)
534 // Remove __it from this container's list
535 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
536 _M_detach_local_single(__it);
539 void
540 _Safe_unordered_container_base::
541 _M_detach_local_single(_Safe_iterator_base* __it) throw ()
543 // Remove __it from this container's list
544 __it->_M_unlink();
545 if (_M_const_local_iterators == __it)
546 _M_const_local_iterators = __it->_M_next;
547 if (_M_local_iterators == __it)
548 _M_local_iterators = __it->_M_next;
552 namespace
554 using _Error_formatter = __gnu_debug::_Error_formatter;
555 using _Parameter = __gnu_debug::_Error_formatter::_Parameter;
557 void
558 get_max_length(std::size_t& max_length)
560 const char* nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
561 if (nptr)
563 char* endptr;
564 const unsigned long ret = std::strtoul(nptr, &endptr, 0);
565 if (*nptr != '\0' && *endptr == '\0')
566 max_length = ret;
570 struct PrintContext
572 PrintContext()
573 : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
574 { get_max_length(_M_max_length); }
576 std::size_t _M_max_length;
577 enum { _M_indent = 4 } ;
578 std::size_t _M_column;
579 bool _M_first_line;
580 bool _M_wordwrap;
583 template<size_t Length>
584 void
585 print_literal(PrintContext& ctx, const char(&word)[Length])
586 { print_word(ctx, word, Length - 1); }
588 void
589 print_word(PrintContext& ctx, const char* word,
590 std::ptrdiff_t count = -1)
592 size_t length = count >= 0 ? count : __builtin_strlen(word);
593 if (length == 0)
594 return;
596 // Consider first '\n' at begining cause it impacts column.
597 if (word[0] == '\n')
599 fprintf(stderr, "\n");
600 ctx._M_column = 1;
601 ++word;
602 --length;
604 if (length == 0)
605 return;
608 size_t visual_length
609 = isspace(word[length - 1]) ? length - 1 : length;
610 if (visual_length == 0
611 || !ctx._M_wordwrap
612 || (ctx._M_column + visual_length < ctx._M_max_length)
613 || (visual_length >= ctx._M_max_length && ctx._M_column == 1))
615 // If this isn't the first line, indent
616 if (ctx._M_column == 1 && !ctx._M_first_line)
618 char spacing[ctx._M_indent + 1];
619 for (int i = 0; i < ctx._M_indent; ++i)
620 spacing[i] = ' ';
621 spacing[ctx._M_indent] = '\0';
622 fprintf(stderr, "%s", spacing);
623 ctx._M_column += ctx._M_indent;
626 int written = fprintf(stderr, "%s", word);
628 if (word[length - 1] == '\n')
630 ctx._M_first_line = false;
631 ctx._M_column = 1;
633 else
634 ctx._M_column += written;
636 else
638 print_literal(ctx, "\n");
639 print_word(ctx, word, count);
643 template<size_t Length>
644 void
645 print_type(PrintContext& ctx,
646 const type_info* info,
647 const char(&unknown_name)[Length])
649 if (!info)
650 print_literal(ctx, unknown_name);
651 else
653 int status;
654 char* demangled_name =
655 __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status);
656 print_word(ctx, status == 0 ? demangled_name : info->name());
657 free(demangled_name);
661 bool
662 print_field(PrintContext& ctx,
663 const char* name, const _Parameter::_Type& type)
665 if (__builtin_strcmp(name, "name") == 0)
667 assert(type._M_name);
668 print_word(ctx, type._M_name);
670 else if (__builtin_strcmp(name, "type") == 0)
671 print_type(ctx, type._M_type, "<unknown type>");
672 else
673 return false;
675 return true;
678 bool
679 print_field(PrintContext& ctx,
680 const char* name, const _Parameter::_Instance& inst)
682 const _Parameter::_Type& type = inst;
683 if (print_field(ctx, name, type))
685 else if (__builtin_strcmp(name, "address") == 0)
687 char buf[64];
688 int ret = __builtin_sprintf(buf, "%p", inst._M_address);
689 print_word(ctx, buf, ret);
691 else
692 return false;
694 return true;
697 void
698 print_field(PrintContext& ctx, const _Parameter& param, const char* name)
700 assert(param._M_kind != _Parameter::__unused_param);
701 const int bufsize = 64;
702 char buf[bufsize];
704 const auto& variant = param._M_variant;
705 switch (param._M_kind)
707 case _Parameter::__iterator:
709 const auto& iterator = variant._M_iterator;
710 if (print_field(ctx, name, iterator))
712 else if (__builtin_strcmp(name, "constness") == 0)
714 static const char*
715 constness_names[_Error_formatter::__last_constness] =
717 "<unknown>",
718 "constant",
719 "mutable"
721 print_word(ctx, constness_names[iterator._M_constness]);
723 else if (__builtin_strcmp(name, "state") == 0)
725 static const char*
726 state_names[_Error_formatter::__last_state] =
728 "<unknown>",
729 "singular",
730 "dereferenceable (start-of-sequence)",
731 "dereferenceable",
732 "past-the-end",
733 "before-begin",
734 "dereferenceable (start-of-reverse-sequence)",
735 "dereferenceable (reverse)",
736 "past-the-reverse-end"
738 print_word(ctx, state_names[iterator._M_state]);
740 else if (__builtin_strcmp(name, "sequence") == 0)
742 assert(iterator._M_sequence);
743 int written = __builtin_sprintf(buf, "%p", iterator._M_sequence);
744 print_word(ctx, buf, written);
746 else if (__builtin_strcmp(name, "seq_type") == 0)
747 print_type(ctx, iterator._M_seq_type, "<unknown seq_type>");
748 else
749 assert(false);
751 break;
753 case _Parameter::__sequence:
754 if (!print_field(ctx, name, variant._M_sequence))
755 assert(false);
756 break;
758 case _Parameter::__integer:
759 if (__builtin_strcmp(name, "name") == 0)
761 assert(variant._M_integer._M_name);
762 print_word(ctx, variant._M_integer._M_name);
764 else
765 assert(false);
766 break;
768 case _Parameter::__string:
769 if (__builtin_strcmp(name, "name") == 0)
771 assert(variant._M_string._M_name);
772 print_word(ctx, variant._M_string._M_name);
774 else
775 assert(false);
776 break;
778 case _Parameter::__instance:
779 if (!print_field(ctx, name, variant._M_instance))
780 assert(false);
781 break;
783 case _Parameter::__iterator_value_type:
784 if (!print_field(ctx, name, variant._M_iterator_value_type))
785 assert(false);
786 break;
788 default:
789 assert(false);
790 break;
794 void
795 print_description(PrintContext& ctx, const _Parameter::_Type& type)
797 if (type._M_name)
799 print_literal(ctx, "\"");
800 print_word(ctx, type._M_name);
801 print_literal(ctx, "\"");
804 print_literal(ctx, " {\n");
806 if (type._M_type)
808 print_literal(ctx, " type = ");
809 print_type(ctx, type._M_type, "<unknown type>");
810 print_literal(ctx, ";\n");
814 void
815 print_description(PrintContext& ctx, const _Parameter::_Instance& inst)
817 const int bufsize = 64;
818 char buf[bufsize];
820 if (inst._M_name)
822 print_literal(ctx, "\"");
823 print_word(ctx, inst._M_name);
824 print_literal(ctx, "\" ");
827 int written
828 = __builtin_sprintf(buf, "@ 0x%p {\n", inst._M_address);
829 print_word(ctx, buf, written);
831 if (inst._M_type)
833 print_literal(ctx, " type = ");
834 print_type(ctx, inst._M_type, "<unknown type>");
838 void
839 print_description(PrintContext& ctx, const _Parameter& param)
841 const int bufsize = 128;
842 char buf[bufsize];
844 const auto& variant = param._M_variant;
845 switch (param._M_kind)
847 case _Parameter::__iterator:
849 const auto& ite = variant._M_iterator;
851 print_literal(ctx, "iterator ");
852 print_description(ctx, ite);
854 if (ite._M_type)
856 if (ite._M_constness != _Error_formatter::__unknown_constness)
858 print_literal(ctx, " (");
859 print_field(ctx, param, "constness");
860 print_literal(ctx, " iterator)");
863 print_literal(ctx, ";\n");
866 if (ite._M_state != _Error_formatter::__unknown_state)
868 print_literal(ctx, " state = ");
869 print_field(ctx, param, "state");
870 print_literal(ctx, ";\n");
873 if (ite._M_sequence)
875 print_literal(ctx, " references sequence ");
876 if (ite._M_seq_type)
878 print_literal(ctx, "with type '");
879 print_field(ctx, param, "seq_type");
880 print_literal(ctx, "' ");
883 int written
884 = __builtin_sprintf(buf, "@ 0x%p\n", ite._M_sequence);
885 print_word(ctx, buf, written);
888 print_literal(ctx, "}\n");
890 break;
892 case _Parameter::__sequence:
893 print_literal(ctx, "sequence ");
894 print_description(ctx, variant._M_sequence);
896 if (variant._M_sequence._M_type)
897 print_literal(ctx, ";\n");
899 print_literal(ctx, "}\n");
900 break;
902 case _Parameter::__instance:
903 print_literal(ctx, "instance ");
904 print_description(ctx, variant._M_instance);
906 if (variant._M_instance._M_type)
907 print_literal(ctx, ";\n");
909 print_literal(ctx, "}\n");
910 break;
912 case _Parameter::__iterator_value_type:
913 print_literal(ctx, "iterator::value_type ");
914 print_description(ctx, variant._M_iterator_value_type);
915 print_literal(ctx, "}\n");
916 break;
918 default:
919 break;
923 void
924 print_string(PrintContext& ctx, const char* string,
925 const _Parameter* parameters, std::size_t num_parameters)
927 const char* start = string;
928 const int bufsize = 128;
929 char buf[bufsize];
930 int bufindex = 0;
932 while (*start)
934 if (isspace(*start))
936 buf[bufindex++] = *start++;
937 buf[bufindex] = '\0';
938 print_word(ctx, buf, bufindex);
939 bufindex = 0;
940 continue;
943 if (!num_parameters || *start != '%')
945 // Normal char or no parameter to look for.
946 buf[bufindex++] = *start++;
947 continue;
950 if (*++start == '%')
952 // Escaped '%'
953 buf[bufindex++] = *start++;
954 continue;
957 // We are on a parameter property reference, we need to flush buffer
958 // first.
959 if (bufindex != 0)
961 buf[bufindex] = '\0';
962 print_word(ctx, buf, bufindex);
963 bufindex = 0;
966 // Get the parameter number
967 assert(*start >= '1' && *start <= '9');
968 size_t param_index = *start - '0' - 1;
969 assert(param_index < num_parameters);
970 const auto& param = parameters[param_index];
972 // '.' separates the parameter number from the field
973 // name, if there is one.
974 ++start;
975 if (*start != '.')
977 assert(*start == ';');
978 ++start;
979 if (param._M_kind == _Parameter::__integer)
981 int written
982 = __builtin_sprintf(buf, "%ld",
983 param._M_variant._M_integer._M_value);
984 print_word(ctx, buf, written);
986 else if (param._M_kind == _Parameter::__string)
987 print_string(ctx, param._M_variant._M_string._M_value,
988 parameters, num_parameters);
989 continue;
992 // Extract the field name we want
993 const int max_field_len = 16;
994 char field[max_field_len];
995 int field_idx = 0;
996 ++start;
997 while (*start != ';')
999 assert(*start);
1000 assert(field_idx < max_field_len - 1);
1001 field[field_idx++] = *start++;
1003 ++start;
1004 field[field_idx] = '\0';
1006 print_field(ctx, param, field);
1009 // Might need to flush.
1010 if (bufindex)
1012 buf[bufindex] = '\0';
1013 print_word(ctx, buf, bufindex);
1018 namespace __gnu_debug
1020 _Error_formatter&
1021 _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
1023 return const_cast<_Error_formatter*>(this)
1024 ->_M_message(_S_debug_messages[__id]);
1027 void
1028 _Error_formatter::_M_error() const
1030 // Emit file & line number information
1031 bool go_to_next_line = false;
1032 PrintContext ctx;
1033 if (_M_file)
1035 print_word(ctx, _M_file);
1036 print_literal(ctx, ":");
1037 go_to_next_line = true;
1040 if (_M_line > 0)
1042 char buf[64];
1043 int written = __builtin_sprintf(buf, "%u:", _M_line);
1044 print_word(ctx, buf, written);
1045 go_to_next_line = true;
1048 if (go_to_next_line)
1049 print_literal(ctx, "\n");
1051 if (ctx._M_max_length)
1052 ctx._M_wordwrap = true;
1054 if (_M_function)
1056 print_literal(ctx, "In function:\n");
1057 print_string(ctx, _M_function, nullptr, 0);
1058 print_literal(ctx, "\n");
1059 ctx._M_first_line = true;
1060 print_literal(ctx, "\n");
1063 // libstdc++/85768
1064 #if 0 //defined _GLIBCXX_HAVE_EXECINFO_H
1066 void* stack[32];
1067 int nb = backtrace(stack, 32);
1069 // Note that we skip current method symbol.
1070 if (nb > 1)
1072 print_literal(ctx, "Backtrace:\n");
1073 auto symbols = backtrace_symbols(stack, nb);
1074 for (int i = 1; i < nb; ++i)
1076 print_word(ctx, symbols[i]);
1077 print_literal(ctx, "\n");
1080 free(symbols);
1081 ctx._M_first_line = true;
1082 print_literal(ctx, "\n");
1085 #endif
1087 print_literal(ctx, "Error: ");
1089 // Print the error message
1090 assert(_M_text);
1091 print_string(ctx, _M_text, _M_parameters, _M_num_parameters);
1092 print_literal(ctx, ".\n");
1094 // Emit descriptions of the objects involved in the operation
1095 ctx._M_first_line = true;
1096 ctx._M_wordwrap = false;
1097 bool has_header = false;
1098 for (unsigned int i = 0; i < _M_num_parameters; ++i)
1100 switch (_M_parameters[i]._M_kind)
1102 case _Parameter::__iterator:
1103 case _Parameter::__sequence:
1104 case _Parameter::__instance:
1105 case _Parameter::__iterator_value_type:
1106 if (!has_header)
1108 print_literal(ctx, "\nObjects involved in the operation:\n");
1109 has_header = true;
1111 print_description(ctx, _M_parameters[i]);
1112 break;
1114 default:
1115 break;
1119 abort();
1122 #if !_GLIBCXX_INLINE_VERSION
1123 // Deprecated methods kept for backward compatibility.
1124 void
1125 _Error_formatter::_Parameter::_M_print_field(
1126 const _Error_formatter*, const char*) const
1129 void
1130 _Error_formatter::_Parameter::_M_print_description(const _Error_formatter*) const
1133 template<typename _Tp>
1134 void
1135 _Error_formatter::_M_format_word(char*, int, const char*, _Tp)
1136 const throw ()
1139 void
1140 _Error_formatter::_M_print_word(const char*) const
1143 void
1144 _Error_formatter::_M_print_string(const char*) const
1147 void
1148 _Error_formatter::_M_get_max_length() const throw ()
1151 // Instantiations.
1152 template
1153 void
1154 _Error_formatter::_M_format_word(char*, int, const char*,
1155 const void*) const;
1157 template
1158 void
1159 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
1161 template
1162 void
1163 _Error_formatter::_M_format_word(char*, int, const char*,
1164 std::size_t) const;
1166 template
1167 void
1168 _Error_formatter::_M_format_word(char*, int, const char*,
1169 const char*) const;
1170 #endif
1172 } // namespace __gnu_debug