1 // Debugging mode support code -*- C++ -*-
3 // Copyright (C) 2003-2022 Free Software Foundation, Inc.
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)
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>
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.
41 #include <algorithm> // for std::min.
43 #include <cxxabi.h> // for __cxa_demangle.
45 #include "mutex_pool.h"
47 #ifdef _GLIBCXX_VERBOSE_ASSERT
52 __glibcxx_assert_fail(const char* file
, int line
,
53 const char* function
, const char* condition
) noexcept
55 fprintf(stderr
, "%s:%d: %s: Assertion '%s' failed.\n",
56 file
, line
, function
, condition
);
66 /** Returns different instances of __mutex depending on the passed address
67 * in order to limit contention without breaking current library binary
70 get_safe_base_mutex(void* address
)
72 // Use arbitrarily __gnu_debug::vector<int> as the container giving
73 // alignment of debug containers.
74 const auto alignbits
= __builtin_ctz(alignof(__gnu_debug::vector
<int>));
75 const unsigned char index
76 = (reinterpret_cast<std::size_t>(address
) >> alignbits
)
77 & __gnu_internal::mask
;
78 return __gnu_internal::get_mutex(index
);
81 #pragma GCC diagnostic push
82 // Suppress -Wabi=2 warnings due to PR c++/51322 mangling change
83 #pragma GCC diagnostic warning "-Wabi=6"
86 swap_its(__gnu_debug::_Safe_sequence_base
& __lhs
,
87 __gnu_debug::_Safe_iterator_base
*& __lhs_its
,
88 __gnu_debug::_Safe_sequence_base
& __rhs
,
89 __gnu_debug::_Safe_iterator_base
*& __rhs_its
)
91 swap(__lhs_its
, __rhs_its
);
92 __gnu_debug::_Safe_iterator_base
* __iter
;
93 for (__iter
= __rhs_its
; __iter
; __iter
= __iter
->_M_next
)
94 __iter
->_M_sequence
= &__rhs
;
95 for (__iter
= __lhs_its
; __iter
; __iter
= __iter
->_M_next
)
96 __iter
->_M_sequence
= &__lhs
;
100 swap_seq_single(__gnu_debug::_Safe_sequence_base
& __lhs
,
101 __gnu_debug::_Safe_sequence_base
& __rhs
)
103 swap(__lhs
._M_version
, __rhs
._M_version
);
104 swap_its(__lhs
, __lhs
._M_iterators
,
105 __rhs
, __rhs
._M_iterators
);
106 swap_its(__lhs
, __lhs
._M_const_iterators
,
107 __rhs
, __rhs
._M_const_iterators
);
109 #pragma GCC diagnostic pop
111 template<typename _Action
>
113 lock_and_run(__gnu_cxx::__mutex
& lhs_mutex
, __gnu_cxx::__mutex
& rhs_mutex
,
116 // We need to lock both sequences to run action.
117 if (&lhs_mutex
== &rhs_mutex
)
119 __gnu_cxx::__scoped_lock
sentry(lhs_mutex
);
124 __gnu_cxx::__scoped_lock
sentry1(&lhs_mutex
< &rhs_mutex
125 ? lhs_mutex
: rhs_mutex
);
126 __gnu_cxx::__scoped_lock
sentry2(&lhs_mutex
< &rhs_mutex
127 ? rhs_mutex
: lhs_mutex
);
133 swap_seq(__gnu_cxx::__mutex
& lhs_mutex
,
134 __gnu_debug::_Safe_sequence_base
& lhs
,
135 __gnu_cxx::__mutex
& rhs_mutex
,
136 __gnu_debug::_Safe_sequence_base
& rhs
)
138 lock_and_run(lhs_mutex
, rhs_mutex
,
139 [&lhs
, &rhs
]() { swap_seq_single(lhs
, rhs
); });
143 swap_ucont_single(__gnu_debug::_Safe_unordered_container_base
& __lhs
,
144 __gnu_debug::_Safe_unordered_container_base
& __rhs
)
146 swap_seq_single(__lhs
, __rhs
);
147 swap_its(__lhs
, __lhs
._M_local_iterators
,
148 __rhs
, __rhs
._M_local_iterators
);
149 swap_its(__lhs
, __lhs
._M_const_local_iterators
,
150 __rhs
, __rhs
._M_const_local_iterators
);
154 swap_ucont(__gnu_cxx::__mutex
& lhs_mutex
,
155 __gnu_debug::_Safe_unordered_container_base
& lhs
,
156 __gnu_cxx::__mutex
& rhs_mutex
,
157 __gnu_debug::_Safe_unordered_container_base
& rhs
)
159 lock_and_run(lhs_mutex
, rhs_mutex
,
160 [&lhs
, &rhs
]() { swap_ucont_single(lhs
, rhs
); });
164 detach_all(__gnu_debug::_Safe_iterator_base
* __iter
)
168 __gnu_debug::_Safe_iterator_base
* __old
= __iter
;
169 __iter
= __iter
->_M_next
;
173 } // anonymous namespace
175 namespace __gnu_debug
177 const char* const _S_debug_messages
[] =
180 "function requires a valid iterator range [%1.name;, %2.name;)",
181 "attempt to insert into container with a singular iterator",
182 "attempt to insert into container with an iterator"
183 " from a different container",
184 "attempt to erase from container with a %2.state; iterator",
185 "attempt to erase from container with an iterator"
186 " from a different container",
187 "attempt to subscript container with out-of-bounds index %2;,"
188 " but container only holds %3; elements",
189 "attempt to access an element in an empty container",
190 "elements in iterator range [%1.name;, %2.name;)"
191 " are not partitioned by the value %3;",
192 "elements in iterator range [%1.name;, %2.name;)"
193 " are not partitioned by the predicate %3; and value %4;",
194 "elements in iterator range [%1.name;, %2.name;) are not sorted",
195 "elements in iterator range [%1.name;, %2.name;)"
196 " are not sorted according to the predicate %3;",
197 "elements in iterator range [%1.name;, %2.name;) do not form a heap",
198 "elements in iterator range [%1.name;, %2.name;)"
199 " do not form a heap with respect to the predicate %3;",
200 // std::bitset checks
201 "attempt to write through a singular bitset reference",
202 "attempt to read from a singular bitset reference",
203 "attempt to flip a singular bitset reference",
205 "attempt to splice a list into itself",
206 "attempt to splice lists with unequal allocators",
207 "attempt to splice elements referenced by a %1.state; iterator",
208 "attempt to splice an iterator from a different container",
209 "splice destination %1.name;"
210 " occurs within source range [%2.name;, %3.name;)",
212 "attempt to initialize an iterator that will immediately become singular",
213 "attempt to copy-construct an iterator from a singular iterator",
214 "attempt to construct a constant iterator"
215 " from a singular mutable iterator",
216 "attempt to copy from a singular iterator",
217 "attempt to dereference a %1.state; iterator",
218 "attempt to increment a %1.state; iterator",
219 "attempt to decrement a %1.state; iterator",
220 "attempt to subscript a %1.state; iterator %2; step from"
221 " its current position, which falls outside its dereferenceable range",
222 "attempt to advance a %1.state; iterator %2; steps,"
223 " which falls outside its valid range",
224 "attempt to retreat a %1.state; iterator %2; steps,"
225 " which falls outside its valid range",
226 "attempt to compare a %1.state; iterator to a %2.state; iterator",
227 "attempt to compare iterators from different sequences",
228 "attempt to order a %1.state; iterator to a %2.state; iterator",
229 "attempt to order iterators from different sequences",
230 "attempt to compute the difference between a %1.state;"
231 " iterator to a %2.state; iterator",
232 "attempt to compute the different between two iterators"
233 " from different sequences",
235 "attempt to dereference an end-of-stream istream_iterator",
236 "attempt to increment an end-of-stream istream_iterator",
238 "attempt to output via an ostream_iterator with no associated stream",
239 // istreambuf_iterator
240 "attempt to dereference an end-of-stream istreambuf_iterator"
241 " (this is a GNU extension)",
242 "attempt to increment an end-of-stream istreambuf_iterator",
244 "attempt to insert into container after an end iterator",
245 "attempt to erase from container after a %2.state; iterator not followed"
246 " by a dereferenceable one",
247 "function requires a valid iterator range (%2.name;, %3.name;)"
248 ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
249 // std::unordered_container::local_iterator
250 "attempt to compare local iterators from different unordered container"
252 "function requires a non-empty iterator range [%1.name;, %2.name;)",
253 "attempt to self move assign",
254 "attempt to access container with out-of-bounds bucket index %2;,"
255 " container only holds %3; buckets",
256 "load factor shall be positive",
257 "allocators must be equal",
258 "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
260 "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
264 _Safe_sequence_base::
267 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
268 detach_all(_M_iterators
);
271 detach_all(_M_const_iterators
);
272 _M_const_iterators
= 0;
276 _Safe_sequence_base::
279 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
280 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;)
282 _Safe_iterator_base
* __old
= __iter
;
283 __iter
= __iter
->_M_next
;
284 if (__old
->_M_singular())
285 __old
->_M_detach_single();
288 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;)
290 _Safe_iterator_base
* __old
= __iter2
;
291 __iter2
= __iter2
->_M_next
;
292 if (__old
->_M_singular())
293 __old
->_M_detach_single();
298 _Safe_sequence_base::
299 _M_revalidate_singular()
301 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
302 for (_Safe_iterator_base
* __iter
= _M_iterators
; __iter
;
303 __iter
= __iter
->_M_next
)
304 __iter
->_M_version
= _M_version
;
306 for (_Safe_iterator_base
* __iter2
= _M_const_iterators
; __iter2
;
307 __iter2
= __iter2
->_M_next
)
308 __iter2
->_M_version
= _M_version
;
312 _Safe_sequence_base::
313 _M_swap(_Safe_sequence_base
& __x
) noexcept
314 { swap_seq(_M_get_mutex(), *this, __x
._M_get_mutex(), __x
); }
317 _Safe_sequence_base::
318 _M_get_mutex() throw ()
319 { return get_safe_base_mutex(this); }
322 _Safe_sequence_base::
323 _M_attach(_Safe_iterator_base
* __it
, bool __constant
)
325 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
326 _M_attach_single(__it
, __constant
);
330 _Safe_sequence_base::
331 _M_attach_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
333 _Safe_iterator_base
*& __its
=
334 __constant
? _M_const_iterators
: _M_iterators
;
335 __it
->_M_next
= __its
;
337 __it
->_M_next
->_M_prior
= __it
;
342 _Safe_sequence_base::
343 _M_detach(_Safe_iterator_base
* __it
)
345 // Remove __it from this sequence's list
346 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
347 _M_detach_single(__it
);
351 _Safe_sequence_base::
352 _M_detach_single(_Safe_iterator_base
* __it
) throw ()
354 // Remove __it from this sequence's list
356 if (_M_const_iterators
== __it
)
357 _M_const_iterators
= __it
->_M_next
;
358 if (_M_iterators
== __it
)
359 _M_iterators
= __it
->_M_next
;
363 _Safe_iterator_base::
364 _M_attach(_Safe_sequence_base
* __seq
, bool __constant
)
368 // Attach to the new sequence (if there is one)
372 _M_version
= _M_sequence
->_M_version
;
373 _M_sequence
->_M_attach(this, __constant
);
378 _Safe_iterator_base::
379 _M_attach_single(_Safe_sequence_base
* __seq
, bool __constant
) throw ()
383 // Attach to the new sequence (if there is one)
387 _M_version
= _M_sequence
->_M_version
;
388 _M_sequence
->_M_attach_single(this, __constant
);
393 _Safe_iterator_base::
396 // This function can run concurrently with the sequence destructor,
397 // so there is a TOCTTOU race here: the sequence could be destroyed
398 // after we check that _M_sequence is not null. Use the pointer value
399 // to acquire the mutex (rather than via _M_sequence->_M_get_mutex()).
400 // If the sequence destructor runs between loading the pointer and
401 // locking the mutex, it will detach this iterator and set _M_sequence
402 // to null, and then _M_detach_single() will do nothing.
403 if (auto seq
= __atomic_load_n(&_M_sequence
, __ATOMIC_ACQUIRE
))
405 __gnu_cxx::__scoped_lock
sentry(get_safe_base_mutex(seq
));
411 _Safe_iterator_base::
412 _M_detach_single() throw ()
416 _M_sequence
->_M_detach_single(this);
422 _Safe_iterator_base::
425 __atomic_store_n(&_M_sequence
, (_Safe_sequence_base
*)0, __ATOMIC_RELEASE
);
432 _Safe_iterator_base::
433 _M_singular() const throw ()
434 { return !_M_sequence
|| _M_version
!= _M_sequence
->_M_version
; }
437 _Safe_iterator_base::
438 _M_can_compare(const _Safe_iterator_base
& __x
) const throw ()
439 { return _M_sequence
== __x
._M_sequence
; }
442 _Safe_iterator_base::
443 _M_get_mutex() throw ()
444 { return _M_sequence
->_M_get_mutex(); }
446 _Safe_unordered_container_base
*
447 _Safe_local_iterator_base::
448 _M_get_container() const noexcept
449 { return static_cast<_Safe_unordered_container_base
*>(_M_sequence
); }
452 _Safe_local_iterator_base::
453 _M_attach(_Safe_sequence_base
* __cont
, bool __constant
)
457 // Attach to the new container (if there is one)
460 _M_sequence
= __cont
;
461 _M_version
= _M_sequence
->_M_version
;
462 _M_get_container()->_M_attach_local(this, __constant
);
467 _Safe_local_iterator_base::
468 _M_attach_single(_Safe_sequence_base
* __cont
, bool __constant
) throw ()
472 // Attach to the new container (if there is one)
475 _M_sequence
= __cont
;
476 _M_version
= _M_sequence
->_M_version
;
477 _M_get_container()->_M_attach_local_single(this, __constant
);
482 _Safe_local_iterator_base::
485 if (auto seq
= __atomic_load_n(&_M_sequence
, __ATOMIC_ACQUIRE
))
487 __gnu_cxx::__scoped_lock
sentry(get_safe_base_mutex(seq
));
493 _Safe_local_iterator_base::
494 _M_detach_single() throw ()
498 _M_get_container()->_M_detach_local_single(this);
504 _Safe_unordered_container_base::
507 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
508 detach_all(_M_iterators
);
511 detach_all(_M_const_iterators
);
512 _M_const_iterators
= 0;
514 detach_all(_M_local_iterators
);
515 _M_local_iterators
= 0;
517 detach_all(_M_const_local_iterators
);
518 _M_const_local_iterators
= 0;
522 _Safe_unordered_container_base::
523 _M_swap(_Safe_unordered_container_base
& __x
) noexcept
524 { swap_ucont(_M_get_mutex(), *this, __x
._M_get_mutex(), __x
); }
527 _Safe_unordered_container_base::
528 _M_attach_local(_Safe_iterator_base
* __it
, bool __constant
)
530 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
531 _M_attach_local_single(__it
, __constant
);
535 _Safe_unordered_container_base::
536 _M_attach_local_single(_Safe_iterator_base
* __it
, bool __constant
) throw ()
538 _Safe_iterator_base
*& __its
=
539 __constant
? _M_const_local_iterators
: _M_local_iterators
;
540 __it
->_M_next
= __its
;
542 __it
->_M_next
->_M_prior
= __it
;
547 _Safe_unordered_container_base::
548 _M_detach_local(_Safe_iterator_base
* __it
)
550 // Remove __it from this container's list
551 __gnu_cxx::__scoped_lock
sentry(_M_get_mutex());
552 _M_detach_local_single(__it
);
556 _Safe_unordered_container_base::
557 _M_detach_local_single(_Safe_iterator_base
* __it
) throw ()
559 // Remove __it from this container's list
561 if (_M_const_local_iterators
== __it
)
562 _M_const_local_iterators
= __it
->_M_next
;
563 if (_M_local_iterators
== __it
)
564 _M_local_iterators
= __it
->_M_next
;
570 using _Error_formatter
= __gnu_debug::_Error_formatter
;
571 using _Parameter
= __gnu_debug::_Error_formatter::_Parameter
;
574 get_max_length(std::size_t& max_length
)
576 const char* nptr
= std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
580 const unsigned long ret
= std::strtoul(nptr
, &endptr
, 0);
581 if (*nptr
!= '\0' && *endptr
== '\0')
589 : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
590 { get_max_length(_M_max_length
); }
592 static constexpr int _S_indent
= 4;
593 std::size_t _M_max_length
;
594 std::size_t _M_column
;
599 using _Print_func_t
= void (PrintContext
&, const char*, ptrdiff_t);
601 template<size_t Length
>
603 print_literal(PrintContext
& ctx
, const char(&word
)[Length
])
604 { print_word(ctx
, word
, Length
- 1); }
607 print_raw(PrintContext
& ctx
, const char* str
, ptrdiff_t nbc
= -1)
610 ctx
._M_column
+= fprintf(stderr
, "%.*s", (int)nbc
, str
);
612 ctx
._M_column
+= fprintf(stderr
, "%s", str
);
616 print_word(PrintContext
& ctx
, const char* word
, ptrdiff_t nbc
= -1)
618 size_t length
= nbc
>= 0 ? nbc
: __builtin_strlen(word
);
622 // First consider '\n' at the beginning because it impacts the column.
625 fprintf(stderr
, "\n");
635 = isspace((unsigned char)word
[length
- 1]) ? length
- 1 : length
;
636 if (visual_length
== 0
638 || (ctx
._M_column
+ visual_length
< ctx
._M_max_length
)
639 || (visual_length
>= ctx
._M_max_length
&& ctx
._M_column
== 1))
641 // If this isn't the first line, indent
642 if (ctx
._M_column
== 1 && !ctx
._M_first_line
)
644 const char spacing
[PrintContext::_S_indent
+ 1] = " ";
645 print_raw(ctx
, spacing
, PrintContext::_S_indent
);
648 int written
= fprintf(stderr
, "%.*s", (int)length
, word
);
650 if (word
[length
- 1] == '\n')
652 ctx
._M_first_line
= false;
656 ctx
._M_column
+= written
;
660 print_literal(ctx
, "\n");
661 print_word(ctx
, word
, nbc
);
666 pretty_print(PrintContext
& ctx
, const char* str
, _Print_func_t print_func
)
668 const char cxx1998
[] = "cxx1998::";
671 if (auto pos
= strstr(str
, "__"))
674 print_func(ctx
, str
, pos
- str
);
676 pos
+= 2; // advance past "__"
677 if (memcmp(pos
, cxx1998
, 9) == 0)
678 pos
+= 9; // advance part "cxx1998::"
684 print_func(ctx
, str
, -1);
690 template<size_t Length
>
692 print_type_info(PrintContext
& ctx
,
693 const type_info
* info
,
694 const char(&unknown_name
)[Length
])
697 print_literal(ctx
, unknown_name
);
701 char* demangled_name
=
702 __cxxabiv1::__cxa_demangle(info
->name(), NULL
, NULL
, &status
);
704 pretty_print(ctx
, demangled_name
, &print_word
);
706 print_word(ctx
, info
->name());
707 free(demangled_name
);
712 print_address(PrintContext
& ctx
, const char* fmt
, const void* address
)
715 int written
= __builtin_sprintf(buf
, fmt
, address
);
716 print_word(ctx
, buf
, written
);
720 print_address(PrintContext
& ctx
, const void* address
)
721 { print_address(ctx
, "%p", address
); }
724 print_integer(PrintContext
& ctx
, long integer
)
727 int written
= __builtin_sprintf(buf
, "%ld", integer
);
728 print_word(ctx
, buf
, written
);
732 print_named_name(PrintContext
& ctx
, const _Parameter::_Named
& named
)
734 assert(named
._M_name
);
735 pretty_print(ctx
, named
._M_name
, print_word
);
738 template<typename _Iterator
>
740 print_iterator_constness(PrintContext
& ctx
, const _Iterator
& iterator
)
743 constness_names
[_Error_formatter::__last_constness
] =
745 "<unknown constness>",
749 print_word(ctx
, constness_names
[iterator
._M_constness
]);
752 template<typename _Iterator
>
754 print_iterator_state(PrintContext
& ctx
, const _Iterator
& iterator
)
757 state_names
[_Error_formatter::__last_state
] =
761 "dereferenceable (start-of-sequence)",
765 "dereferenceable (start-of-reverse-sequence)",
766 "dereferenceable (reverse)",
767 "past-the-reverse-end"
769 print_word(ctx
, state_names
[iterator
._M_state
]);
772 template<typename _Iterator
>
774 print_iterator_seq_type(PrintContext
& ctx
, const _Iterator
& iterator
)
775 { print_type_info(ctx
, iterator
._M_seq_type
, "<unknown seq_type>"); }
778 print_named_field(PrintContext
& ctx
,
779 const char* fname
, const _Parameter::_Named
& named
)
781 if (__builtin_strcmp(fname
, "name") == 0)
782 print_named_name(ctx
, named
);
790 print_type_field(PrintContext
& ctx
,
791 const char* fname
, const _Parameter::_Type
& type
)
793 if (print_named_field(ctx
, fname
, type
))
795 else if (__builtin_strcmp(fname
, "type") == 0)
796 print_type_info(ctx
, type
._M_type
, "<unknown type>");
804 print_instance_field(PrintContext
& ctx
,
805 const char* fname
, const _Parameter::_Instance
& inst
)
807 if (print_type_field(ctx
, fname
, inst
))
809 else if (__builtin_strcmp(fname
, "address") == 0)
810 print_address(ctx
, inst
._M_address
);
817 template<typename _Iterator
>
819 print_iterator_field(PrintContext
& ctx
,
820 const char* fname
, const _Iterator
& iterator
)
822 if (print_instance_field(ctx
, fname
, iterator
))
824 else if (__builtin_strcmp(fname
, "constness") == 0)
825 print_iterator_constness(ctx
, iterator
);
826 else if (__builtin_strcmp(fname
, "state") == 0)
827 print_iterator_state(ctx
, iterator
);
828 else if (__builtin_strcmp(fname
, "sequence") == 0)
830 assert(iterator
._M_sequence
);
831 print_address(ctx
, iterator
._M_sequence
);
833 else if (__builtin_strcmp(fname
, "seq_type") == 0)
834 print_iterator_seq_type(ctx
, iterator
);
842 print_field(PrintContext
& ctx
, const _Parameter
& param
, const char* fname
)
844 assert(param
._M_kind
!= _Parameter::__unused_param
);
846 const auto& variant
= param
._M_variant
;
847 switch (param
._M_kind
)
849 case _Parameter::__iterator
:
850 if (!print_iterator_field(ctx
, fname
, variant
._M_iterator
))
854 case _Parameter::__sequence
:
855 if (!print_instance_field(ctx
, fname
, variant
._M_sequence
))
859 case _Parameter::__integer
:
860 if (!print_named_field(ctx
, fname
, variant
._M_integer
))
864 case _Parameter::__string
:
865 if (!print_named_field(ctx
, fname
, variant
._M_string
))
869 case _Parameter::__instance
:
870 if (!print_instance_field(ctx
, fname
, variant
._M_instance
))
874 case _Parameter::__iterator_value_type
:
875 if (!print_type_field(ctx
, fname
, variant
._M_iterator_value_type
))
886 print_quoted_named_name(PrintContext
& ctx
, const _Parameter::_Named
& named
)
890 print_literal(ctx
, "\"");
891 print_named_name(ctx
, named
);
892 print_literal(ctx
, "\" ");
897 print_type_type(PrintContext
& ctx
, const _Parameter::_Type
& type
,
898 bool close_desc
= true)
902 print_literal(ctx
, " type = ");
903 print_type_info(ctx
, type
._M_type
, "<unknown type>");
905 print_literal(ctx
, ";\n");
910 print_type(PrintContext
& ctx
, const _Parameter::_Type
& type
)
912 print_quoted_named_name(ctx
, type
);
913 print_literal(ctx
, " {\n");
914 print_type_type(ctx
, type
);
915 print_literal(ctx
, "}\n");
919 print_instance(PrintContext
& ctx
, const _Parameter::_Instance
& inst
,
920 bool close_desc
= true)
922 print_quoted_named_name(ctx
, inst
);
923 print_address(ctx
, "@ %p {\n", inst
._M_address
);
924 print_type_type(ctx
, inst
, close_desc
);
927 print_literal(ctx
, "}\n");
931 print_description(PrintContext
& ctx
, const _Parameter
& param
)
933 const auto& variant
= param
._M_variant
;
934 switch (param
._M_kind
)
936 case _Parameter::__iterator
:
938 const auto& ite
= variant
._M_iterator
;
940 print_literal(ctx
, "iterator ");
941 print_instance(ctx
, ite
, false);
945 if (ite
._M_constness
!= _Error_formatter::__unknown_constness
)
947 print_literal(ctx
, " (");
948 print_iterator_constness(ctx
, ite
);
949 print_literal(ctx
, " iterator)");
952 print_literal(ctx
, ";\n");
955 if (ite
._M_state
!= _Error_formatter::__unknown_state
)
957 print_literal(ctx
, " state = ");
958 print_iterator_state(ctx
, ite
);
959 print_literal(ctx
, ";\n");
964 print_literal(ctx
, " references sequence ");
967 print_literal(ctx
, "with type '");
968 print_iterator_seq_type(ctx
, ite
);
969 print_literal(ctx
, "' ");
972 print_address(ctx
, "@ %p\n", ite
._M_sequence
);
975 print_literal(ctx
, "}\n");
979 case _Parameter::__sequence
:
980 print_literal(ctx
, "sequence ");
981 print_instance(ctx
, variant
._M_sequence
);
984 case _Parameter::__instance
:
985 print_literal(ctx
, "instance ");
986 print_instance(ctx
, variant
._M_instance
);
989 case _Parameter::__iterator_value_type
:
990 print_literal(ctx
, "iterator::value_type ");
991 print_type(ctx
, variant
._M_iterator_value_type
);
1000 print_string(PrintContext
& ctx
, const char* str
, ptrdiff_t nbc
,
1001 const _Parameter
* parameters
, std::size_t num_parameters
)
1003 const char* start
= str
;
1004 const char* end
= nbc
>= 0 ? start
+ nbc
: nullptr;
1006 while ((end
&& str
!= end
) || (!end
&& *str
))
1008 if (isspace((unsigned char)*str
))
1011 print_word(ctx
, start
, str
- start
);
1016 if (!parameters
|| *str
!= '%')
1018 // Normal char or no parameter to look for.
1026 print_word(ctx
, start
, str
- start
);
1032 // We are on a parameter property reference, we need to flush buffer
1036 // Avoid printing the '%'.
1037 if (str
- start
> 1)
1038 print_word(ctx
, start
, str
- start
- 1);
1042 // Get the parameter number
1043 assert(*str
>= '1' && *str
<= '9');
1044 size_t param_index
= *str
- '0' - 1;
1045 assert(param_index
< num_parameters
);
1046 const auto& param
= parameters
[param_index
];
1048 // '.' separates the parameter number from the field
1049 // name, if there is one.
1053 assert(*str
== ';');
1055 if (param
._M_kind
== _Parameter::__integer
)
1056 print_integer(ctx
, param
._M_variant
._M_integer
._M_value
);
1057 else if (param
._M_kind
== _Parameter::__string
)
1058 print_string(ctx
, param
._M_variant
._M_string
._M_value
, -1,
1059 parameters
, num_parameters
);
1064 // Extract the field name we want
1065 const int max_field_len
= 16;
1066 char field
[max_field_len
];
1072 assert(field_idx
< max_field_len
- 1);
1073 field
[field_idx
++] = *str
++;
1076 field
[field_idx
] = '\0';
1078 print_field(ctx
, param
, field
);
1082 // Might need to flush.
1084 print_word(ctx
, start
, str
- start
);
1088 print_string(PrintContext
& ctx
, const char* str
, ptrdiff_t nbc
)
1089 { print_string(ctx
, str
, nbc
, nullptr, 0); }
1092 namespace __gnu_debug
1095 _Error_formatter::_M_message(_Debug_msg_id __id
) const throw ()
1097 return const_cast<_Error_formatter
*>(this)
1098 ->_M_message(_S_debug_messages
[__id
]);
1102 _Error_formatter::_M_error() const
1104 // Emit file & line number information
1105 bool go_to_next_line
= false;
1109 print_raw(ctx
, _M_file
);
1110 print_literal(ctx
, ":");
1111 go_to_next_line
= true;
1116 ctx
._M_column
+= fprintf(stderr
, "%u", _M_line
);
1117 print_literal(ctx
, ":");
1118 go_to_next_line
= true;
1121 if (go_to_next_line
)
1122 print_literal(ctx
, "\n");
1124 if (ctx
._M_max_length
)
1125 ctx
._M_wordwrap
= true;
1129 print_literal(ctx
, "In function:\n");
1130 pretty_print(ctx
, _M_function
, &print_string
);
1131 print_literal(ctx
, "\n");
1132 ctx
._M_first_line
= true;
1133 print_literal(ctx
, "\n");
1136 print_literal(ctx
, "Error: ");
1138 // Print the error message
1140 print_string(ctx
, _M_text
, -1, _M_parameters
, _M_num_parameters
);
1141 print_literal(ctx
, ".\n");
1143 // Emit descriptions of the objects involved in the operation
1144 ctx
._M_first_line
= true;
1145 ctx
._M_wordwrap
= false;
1146 bool has_header
= false;
1147 for (unsigned int i
= 0; i
< _M_num_parameters
; ++i
)
1149 switch (_M_parameters
[i
]._M_kind
)
1151 case _Parameter::__iterator
:
1152 case _Parameter::__sequence
:
1153 case _Parameter::__instance
:
1154 case _Parameter::__iterator_value_type
:
1157 print_literal(ctx
, "\nObjects involved in the operation:\n");
1160 print_description(ctx
, _M_parameters
[i
]);
1171 #if !_GLIBCXX_INLINE_VERSION
1172 // Deprecated methods kept for backward compatibility.
1174 _Error_formatter::_Parameter::_M_print_field(
1175 const _Error_formatter
*, const char*) const
1179 _Error_formatter::_Parameter::_M_print_description(const _Error_formatter
*) const
1182 template<typename _Tp
>
1184 _Error_formatter::_M_format_word(char*, int, const char*, _Tp
)
1189 _Error_formatter::_M_print_word(const char*) const
1193 _Error_formatter::_M_print_string(const char*) const
1197 _Error_formatter::_M_get_max_length() const throw ()
1203 _Error_formatter::_M_format_word(char*, int, const char*,
1208 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
1212 _Error_formatter::_M_format_word(char*, int, const char*,
1217 _Error_formatter::_M_format_word(char*, int, const char*,
1221 } // namespace __gnu_debug