]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/src/c++11/debug.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / src / c++11 / debug.cc
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 fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.\n",
56 file, line, function, condition);
57 abort();
58 }
59 }
60 #endif
61
62 using namespace std;
63
64 namespace
65 {
66 /** Returns different instances of __mutex depending on the passed address
67 * in order to limit contention without breaking current library binary
68 * compatibility. */
69 __gnu_cxx::__mutex&
70 get_safe_base_mutex(void* address)
71 {
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);
79 }
80
81 #pragma GCC diagnostic push
82 // Suppress -Wabi=2 warnings due to PR c++/51322 mangling change
83 #pragma GCC diagnostic warning "-Wabi=6"
84
85 void
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)
90 {
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;
97 }
98
99 void
100 swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
101 __gnu_debug::_Safe_sequence_base& __rhs)
102 {
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);
108 }
109 #pragma GCC diagnostic pop
110
111 template<typename _Action>
112 void
113 lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex,
114 _Action action)
115 {
116 // We need to lock both sequences to run action.
117 if (&lhs_mutex == &rhs_mutex)
118 {
119 __gnu_cxx::__scoped_lock sentry(lhs_mutex);
120 action();
121 }
122 else
123 {
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);
128 action();
129 }
130 }
131
132 void
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)
137 {
138 lock_and_run(lhs_mutex, rhs_mutex,
139 [&lhs, &rhs]() { swap_seq_single(lhs, rhs); });
140 }
141
142 void
143 swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs,
144 __gnu_debug::_Safe_unordered_container_base& __rhs)
145 {
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);
151 }
152
153 void
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)
158 {
159 lock_and_run(lhs_mutex, rhs_mutex,
160 [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); });
161 }
162
163 void
164 detach_all(__gnu_debug::_Safe_iterator_base* __iter)
165 {
166 for (; __iter;)
167 {
168 __gnu_debug::_Safe_iterator_base* __old = __iter;
169 __iter = __iter->_M_next;
170 __old->_M_reset();
171 }
172 }
173 } // anonymous namespace
174
175 namespace __gnu_debug
176 {
177 const char* const _S_debug_messages[] =
178 {
179 // General Checks
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",
204 // std::list checks
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;)",
211 // iterator checks
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",
234 // istream_iterator
235 "attempt to dereference an end-of-stream istream_iterator",
236 "attempt to increment an end-of-stream istream_iterator",
237 // ostream_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",
243 // std::forward_list
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"
251 " buckets",
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"
259 " container",
260 "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
261 };
262
263 void
264 _Safe_sequence_base::
265 _M_detach_all()
266 {
267 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
268 detach_all(_M_iterators);
269 _M_iterators = 0;
270
271 detach_all(_M_const_iterators);
272 _M_const_iterators = 0;
273 }
274
275 void
276 _Safe_sequence_base::
277 _M_detach_singular()
278 {
279 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
280 for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
281 {
282 _Safe_iterator_base* __old = __iter;
283 __iter = __iter->_M_next;
284 if (__old->_M_singular())
285 __old->_M_detach_single();
286 }
287
288 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
289 {
290 _Safe_iterator_base* __old = __iter2;
291 __iter2 = __iter2->_M_next;
292 if (__old->_M_singular())
293 __old->_M_detach_single();
294 }
295 }
296
297 void
298 _Safe_sequence_base::
299 _M_revalidate_singular()
300 {
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;
305
306 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
307 __iter2 = __iter2->_M_next)
308 __iter2->_M_version = _M_version;
309 }
310
311 void
312 _Safe_sequence_base::
313 _M_swap(_Safe_sequence_base& __x) noexcept
314 { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
315
316 __gnu_cxx::__mutex&
317 _Safe_sequence_base::
318 _M_get_mutex() throw ()
319 { return get_safe_base_mutex(this); }
320
321 void
322 _Safe_sequence_base::
323 _M_attach(_Safe_iterator_base* __it, bool __constant)
324 {
325 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
326 _M_attach_single(__it, __constant);
327 }
328
329 void
330 _Safe_sequence_base::
331 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
332 {
333 _Safe_iterator_base*& __its =
334 __constant ? _M_const_iterators : _M_iterators;
335 __it->_M_next = __its;
336 if (__it->_M_next)
337 __it->_M_next->_M_prior = __it;
338 __its = __it;
339 }
340
341 void
342 _Safe_sequence_base::
343 _M_detach(_Safe_iterator_base* __it)
344 {
345 // Remove __it from this sequence's list
346 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
347 _M_detach_single(__it);
348 }
349
350 void
351 _Safe_sequence_base::
352 _M_detach_single(_Safe_iterator_base* __it) throw ()
353 {
354 // Remove __it from this sequence's list
355 __it->_M_unlink();
356 if (_M_const_iterators == __it)
357 _M_const_iterators = __it->_M_next;
358 if (_M_iterators == __it)
359 _M_iterators = __it->_M_next;
360 }
361
362 void
363 _Safe_iterator_base::
364 _M_attach(_Safe_sequence_base* __seq, bool __constant)
365 {
366 _M_detach();
367
368 // Attach to the new sequence (if there is one)
369 if (__seq)
370 {
371 _M_sequence = __seq;
372 _M_version = _M_sequence->_M_version;
373 _M_sequence->_M_attach(this, __constant);
374 }
375 }
376
377 void
378 _Safe_iterator_base::
379 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
380 {
381 _M_detach_single();
382
383 // Attach to the new sequence (if there is one)
384 if (__seq)
385 {
386 _M_sequence = __seq;
387 _M_version = _M_sequence->_M_version;
388 _M_sequence->_M_attach_single(this, __constant);
389 }
390 }
391
392 void
393 _Safe_iterator_base::
394 _M_detach()
395 {
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))
404 {
405 __gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq));
406 _M_detach_single();
407 }
408 }
409
410 void
411 _Safe_iterator_base::
412 _M_detach_single() throw ()
413 {
414 if (_M_sequence)
415 {
416 _M_sequence->_M_detach_single(this);
417 _M_reset();
418 }
419 }
420
421 void
422 _Safe_iterator_base::
423 _M_reset() throw ()
424 {
425 __atomic_store_n(&_M_sequence, (_Safe_sequence_base*)0, __ATOMIC_RELEASE);
426 _M_version = 0;
427 _M_prior = 0;
428 _M_next = 0;
429 }
430
431 bool
432 _Safe_iterator_base::
433 _M_singular() const throw ()
434 { return !_M_sequence || _M_version != _M_sequence->_M_version; }
435
436 bool
437 _Safe_iterator_base::
438 _M_can_compare(const _Safe_iterator_base& __x) const throw ()
439 { return _M_sequence == __x._M_sequence; }
440
441 __gnu_cxx::__mutex&
442 _Safe_iterator_base::
443 _M_get_mutex() throw ()
444 { return _M_sequence->_M_get_mutex(); }
445
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); }
450
451 void
452 _Safe_local_iterator_base::
453 _M_attach(_Safe_sequence_base* __cont, bool __constant)
454 {
455 _M_detach();
456
457 // Attach to the new container (if there is one)
458 if (__cont)
459 {
460 _M_sequence = __cont;
461 _M_version = _M_sequence->_M_version;
462 _M_get_container()->_M_attach_local(this, __constant);
463 }
464 }
465
466 void
467 _Safe_local_iterator_base::
468 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
469 {
470 _M_detach_single();
471
472 // Attach to the new container (if there is one)
473 if (__cont)
474 {
475 _M_sequence = __cont;
476 _M_version = _M_sequence->_M_version;
477 _M_get_container()->_M_attach_local_single(this, __constant);
478 }
479 }
480
481 void
482 _Safe_local_iterator_base::
483 _M_detach()
484 {
485 if (auto seq = __atomic_load_n(&_M_sequence, __ATOMIC_ACQUIRE))
486 {
487 __gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq));
488 _M_detach_single();
489 }
490 }
491
492 void
493 _Safe_local_iterator_base::
494 _M_detach_single() throw ()
495 {
496 if (_M_sequence)
497 {
498 _M_get_container()->_M_detach_local_single(this);
499 _M_reset();
500 }
501 }
502
503 void
504 _Safe_unordered_container_base::
505 _M_detach_all()
506 {
507 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
508 detach_all(_M_iterators);
509 _M_iterators = 0;
510
511 detach_all(_M_const_iterators);
512 _M_const_iterators = 0;
513
514 detach_all(_M_local_iterators);
515 _M_local_iterators = 0;
516
517 detach_all(_M_const_local_iterators);
518 _M_const_local_iterators = 0;
519 }
520
521 void
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); }
525
526 void
527 _Safe_unordered_container_base::
528 _M_attach_local(_Safe_iterator_base* __it, bool __constant)
529 {
530 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
531 _M_attach_local_single(__it, __constant);
532 }
533
534 void
535 _Safe_unordered_container_base::
536 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
537 {
538 _Safe_iterator_base*& __its =
539 __constant ? _M_const_local_iterators : _M_local_iterators;
540 __it->_M_next = __its;
541 if (__it->_M_next)
542 __it->_M_next->_M_prior = __it;
543 __its = __it;
544 }
545
546 void
547 _Safe_unordered_container_base::
548 _M_detach_local(_Safe_iterator_base* __it)
549 {
550 // Remove __it from this container's list
551 __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
552 _M_detach_local_single(__it);
553 }
554
555 void
556 _Safe_unordered_container_base::
557 _M_detach_local_single(_Safe_iterator_base* __it) throw ()
558 {
559 // Remove __it from this container's list
560 __it->_M_unlink();
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;
565 }
566 }
567
568 namespace
569 {
570 using _Error_formatter = __gnu_debug::_Error_formatter;
571 using _Parameter = __gnu_debug::_Error_formatter::_Parameter;
572
573 void
574 get_max_length(std::size_t& max_length)
575 {
576 const char* nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
577 if (nptr)
578 {
579 char* endptr;
580 const unsigned long ret = std::strtoul(nptr, &endptr, 0);
581 if (*nptr != '\0' && *endptr == '\0')
582 max_length = ret;
583 }
584 }
585
586 struct PrintContext
587 {
588 PrintContext()
589 : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
590 { get_max_length(_M_max_length); }
591
592 static constexpr int _S_indent = 4;
593 std::size_t _M_max_length;
594 std::size_t _M_column;
595 bool _M_first_line;
596 bool _M_wordwrap;
597 };
598
599 using _Print_func_t = void (PrintContext&, const char*, ptrdiff_t);
600
601 template<size_t Length>
602 void
603 print_literal(PrintContext& ctx, const char(&word)[Length])
604 { print_word(ctx, word, Length - 1); }
605
606 void
607 print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1)
608 {
609 if (nbc >= 0)
610 ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str);
611 else
612 ctx._M_column += fprintf(stderr, "%s", str);
613 }
614
615 void
616 print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
617 {
618 size_t length = nbc >= 0 ? nbc : __builtin_strlen(word);
619 if (length == 0)
620 return;
621
622 // First consider '\n' at the beginning because it impacts the column.
623 if (word[0] == '\n')
624 {
625 fprintf(stderr, "\n");
626 ctx._M_column = 1;
627 ++word;
628 --length;
629
630 if (length == 0)
631 return;
632 }
633
634 size_t visual_length
635 = isspace((unsigned char)word[length - 1]) ? length - 1 : length;
636 if (visual_length == 0
637 || !ctx._M_wordwrap
638 || (ctx._M_column + visual_length < ctx._M_max_length)
639 || (visual_length >= ctx._M_max_length && ctx._M_column == 1))
640 {
641 // If this isn't the first line, indent
642 if (ctx._M_column == 1 && !ctx._M_first_line)
643 {
644 const char spacing[PrintContext::_S_indent + 1] = " ";
645 print_raw(ctx, spacing, PrintContext::_S_indent);
646 }
647
648 int written = fprintf(stderr, "%.*s", (int)length, word);
649
650 if (word[length - 1] == '\n')
651 {
652 ctx._M_first_line = false;
653 ctx._M_column = 1;
654 }
655 else
656 ctx._M_column += written;
657 }
658 else
659 {
660 print_literal(ctx, "\n");
661 print_word(ctx, word, nbc);
662 }
663 }
664
665 void
666 pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func)
667 {
668 const char cxx1998[] = "cxx1998::";
669 for (;;)
670 {
671 if (auto pos = strstr(str, "__"))
672 {
673 if (pos != str)
674 print_func(ctx, str, pos - str);
675
676 pos += 2; // advance past "__"
677 if (memcmp(pos, cxx1998, 9) == 0)
678 pos += 9; // advance part "cxx1998::"
679
680 str = pos;
681 }
682 else
683 {
684 print_func(ctx, str, -1);
685 break;
686 }
687 }
688 }
689
690 template<size_t Length>
691 void
692 print_type_info(PrintContext& ctx,
693 const type_info* info,
694 const char(&unknown_name)[Length])
695 {
696 if (!info)
697 print_literal(ctx, unknown_name);
698 else
699 {
700 int status;
701 char* demangled_name =
702 __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status);
703 if (status == 0)
704 pretty_print(ctx, demangled_name, &print_word);
705 else
706 print_word(ctx, info->name());
707 free(demangled_name);
708 }
709 }
710
711 void
712 print_address(PrintContext& ctx, const char* fmt, const void* address)
713 {
714 char buf[128];
715 int written = __builtin_sprintf(buf, fmt, address);
716 print_word(ctx, buf, written);
717 }
718
719 void
720 print_address(PrintContext& ctx, const void* address)
721 { print_address(ctx, "%p", address); }
722
723 void
724 print_integer(PrintContext& ctx, long integer)
725 {
726 char buf[64];
727 int written = __builtin_sprintf(buf, "%ld", integer);
728 print_word(ctx, buf, written);
729 }
730
731 void
732 print_named_name(PrintContext& ctx, const _Parameter::_Named& named)
733 {
734 assert(named._M_name);
735 pretty_print(ctx, named._M_name, print_word);
736 }
737
738 template<typename _Iterator>
739 void
740 print_iterator_constness(PrintContext& ctx, const _Iterator& iterator)
741 {
742 static const char*
743 constness_names[_Error_formatter::__last_constness] =
744 {
745 "<unknown constness>",
746 "constant",
747 "mutable"
748 };
749 print_word(ctx, constness_names[iterator._M_constness]);
750 }
751
752 template<typename _Iterator>
753 void
754 print_iterator_state(PrintContext& ctx, const _Iterator& iterator)
755 {
756 static const char*
757 state_names[_Error_formatter::__last_state] =
758 {
759 "<unknown state>",
760 "singular",
761 "dereferenceable (start-of-sequence)",
762 "dereferenceable",
763 "past-the-end",
764 "before-begin",
765 "dereferenceable (start-of-reverse-sequence)",
766 "dereferenceable (reverse)",
767 "past-the-reverse-end"
768 };
769 print_word(ctx, state_names[iterator._M_state]);
770 }
771
772 template<typename _Iterator>
773 void
774 print_iterator_seq_type(PrintContext& ctx, const _Iterator& iterator)
775 { print_type_info(ctx, iterator._M_seq_type, "<unknown seq_type>"); }
776
777 bool
778 print_named_field(PrintContext& ctx,
779 const char* fname, const _Parameter::_Named& named)
780 {
781 if (__builtin_strcmp(fname, "name") == 0)
782 print_named_name(ctx, named);
783 else
784 return false;
785
786 return true;
787 }
788
789 bool
790 print_type_field(PrintContext& ctx,
791 const char* fname, const _Parameter::_Type& type)
792 {
793 if (print_named_field(ctx, fname, type))
794 { }
795 else if (__builtin_strcmp(fname, "type") == 0)
796 print_type_info(ctx, type._M_type, "<unknown type>");
797 else
798 return false;
799
800 return true;
801 }
802
803 bool
804 print_instance_field(PrintContext& ctx,
805 const char* fname, const _Parameter::_Instance& inst)
806 {
807 if (print_type_field(ctx, fname, inst))
808 { }
809 else if (__builtin_strcmp(fname, "address") == 0)
810 print_address(ctx, inst._M_address);
811 else
812 return false;
813
814 return true;
815 }
816
817 template<typename _Iterator>
818 bool
819 print_iterator_field(PrintContext& ctx,
820 const char* fname, const _Iterator& iterator)
821 {
822 if (print_instance_field(ctx, fname, iterator))
823 { }
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)
829 {
830 assert(iterator._M_sequence);
831 print_address(ctx, iterator._M_sequence);
832 }
833 else if (__builtin_strcmp(fname, "seq_type") == 0)
834 print_iterator_seq_type(ctx, iterator);
835 else
836 return false;
837
838 return true;
839 }
840
841 void
842 print_field(PrintContext& ctx, const _Parameter& param, const char* fname)
843 {
844 assert(param._M_kind != _Parameter::__unused_param);
845
846 const auto& variant = param._M_variant;
847 switch (param._M_kind)
848 {
849 case _Parameter::__iterator:
850 if (!print_iterator_field(ctx, fname, variant._M_iterator))
851 assert(false);
852 break;
853
854 case _Parameter::__sequence:
855 if (!print_instance_field(ctx, fname, variant._M_sequence))
856 assert(false);
857 break;
858
859 case _Parameter::__integer:
860 if (!print_named_field(ctx, fname, variant._M_integer))
861 assert(false);
862 break;
863
864 case _Parameter::__string:
865 if (!print_named_field(ctx, fname, variant._M_string))
866 assert(false);
867 break;
868
869 case _Parameter::__instance:
870 if (!print_instance_field(ctx, fname, variant._M_instance))
871 assert(false);
872 break;
873
874 case _Parameter::__iterator_value_type:
875 if (!print_type_field(ctx, fname, variant._M_iterator_value_type))
876 assert(false);
877 break;
878
879 default:
880 assert(false);
881 break;
882 }
883 }
884
885 void
886 print_quoted_named_name(PrintContext& ctx, const _Parameter::_Named& named)
887 {
888 if (named._M_name)
889 {
890 print_literal(ctx, "\"");
891 print_named_name(ctx, named);
892 print_literal(ctx, "\" ");
893 }
894 }
895
896 void
897 print_type_type(PrintContext& ctx, const _Parameter::_Type& type,
898 bool close_desc = true)
899 {
900 if (type._M_type)
901 {
902 print_literal(ctx, " type = ");
903 print_type_info(ctx, type._M_type, "<unknown type>");
904 if (close_desc)
905 print_literal(ctx, ";\n");
906 }
907 }
908
909 void
910 print_type(PrintContext& ctx, const _Parameter::_Type& type)
911 {
912 print_quoted_named_name(ctx, type);
913 print_literal(ctx, " {\n");
914 print_type_type(ctx, type);
915 print_literal(ctx, "}\n");
916 }
917
918 void
919 print_instance(PrintContext& ctx, const _Parameter::_Instance& inst,
920 bool close_desc = true)
921 {
922 print_quoted_named_name(ctx, inst);
923 print_address(ctx, "@ %p {\n", inst._M_address);
924 print_type_type(ctx, inst, close_desc);
925
926 if (close_desc)
927 print_literal(ctx, "}\n");
928 }
929
930 void
931 print_description(PrintContext& ctx, const _Parameter& param)
932 {
933 const auto& variant = param._M_variant;
934 switch (param._M_kind)
935 {
936 case _Parameter::__iterator:
937 {
938 const auto& ite = variant._M_iterator;
939
940 print_literal(ctx, "iterator ");
941 print_instance(ctx, ite, false);
942
943 if (ite._M_type)
944 {
945 if (ite._M_constness != _Error_formatter::__unknown_constness)
946 {
947 print_literal(ctx, " (");
948 print_iterator_constness(ctx, ite);
949 print_literal(ctx, " iterator)");
950 }
951
952 print_literal(ctx, ";\n");
953 }
954
955 if (ite._M_state != _Error_formatter::__unknown_state)
956 {
957 print_literal(ctx, " state = ");
958 print_iterator_state(ctx, ite);
959 print_literal(ctx, ";\n");
960 }
961
962 if (ite._M_sequence)
963 {
964 print_literal(ctx, " references sequence ");
965 if (ite._M_seq_type)
966 {
967 print_literal(ctx, "with type '");
968 print_iterator_seq_type(ctx, ite);
969 print_literal(ctx, "' ");
970 }
971
972 print_address(ctx, "@ %p\n", ite._M_sequence);
973 }
974
975 print_literal(ctx, "}\n");
976 }
977 break;
978
979 case _Parameter::__sequence:
980 print_literal(ctx, "sequence ");
981 print_instance(ctx, variant._M_sequence);
982 break;
983
984 case _Parameter::__instance:
985 print_literal(ctx, "instance ");
986 print_instance(ctx, variant._M_instance);
987 break;
988
989 case _Parameter::__iterator_value_type:
990 print_literal(ctx, "iterator::value_type ");
991 print_type(ctx, variant._M_iterator_value_type);
992 break;
993
994 default:
995 break;
996 }
997 }
998
999 void
1000 print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc,
1001 const _Parameter* parameters, std::size_t num_parameters)
1002 {
1003 const char* start = str;
1004 const char* end = nbc >= 0 ? start + nbc : nullptr;
1005
1006 while ((end && str != end) || (!end && *str))
1007 {
1008 if (isspace((unsigned char)*str))
1009 {
1010 ++str;
1011 print_word(ctx, start, str - start);
1012 start = str;
1013 continue;
1014 }
1015
1016 if (!parameters || *str != '%')
1017 {
1018 // Normal char or no parameter to look for.
1019 ++str;
1020 continue;
1021 }
1022
1023 if (*++str == '%')
1024 {
1025 // Escaped '%'
1026 print_word(ctx, start, str - start);
1027 ++str;
1028 start = str;
1029 continue;
1030 }
1031
1032 // We are on a parameter property reference, we need to flush buffer
1033 // first.
1034 if (str != start)
1035 {
1036 // Avoid printing the '%'.
1037 if (str - start > 1)
1038 print_word(ctx, start, str - start - 1);
1039 start = str;
1040 }
1041
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];
1047
1048 // '.' separates the parameter number from the field
1049 // name, if there is one.
1050 ++str;
1051 if (*str != '.')
1052 {
1053 assert(*str == ';');
1054 ++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);
1060 start = str;
1061 continue;
1062 }
1063
1064 // Extract the field name we want
1065 const int max_field_len = 16;
1066 char field[max_field_len];
1067 int field_idx = 0;
1068 ++str;
1069 while (*str != ';')
1070 {
1071 assert(*str);
1072 assert(field_idx < max_field_len - 1);
1073 field[field_idx++] = *str++;
1074 }
1075 ++str;
1076 field[field_idx] = '\0';
1077
1078 print_field(ctx, param, field);
1079 start = str;
1080 }
1081
1082 // Might need to flush.
1083 if (str != start)
1084 print_word(ctx, start, str - start);
1085 }
1086
1087 void
1088 print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc)
1089 { print_string(ctx, str, nbc, nullptr, 0); }
1090 }
1091
1092 namespace __gnu_debug
1093 {
1094 _Error_formatter&
1095 _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
1096 {
1097 return const_cast<_Error_formatter*>(this)
1098 ->_M_message(_S_debug_messages[__id]);
1099 }
1100
1101 void
1102 _Error_formatter::_M_error() const
1103 {
1104 // Emit file & line number information
1105 bool go_to_next_line = false;
1106 PrintContext ctx;
1107 if (_M_file)
1108 {
1109 print_raw(ctx, _M_file);
1110 print_literal(ctx, ":");
1111 go_to_next_line = true;
1112 }
1113
1114 if (_M_line > 0)
1115 {
1116 ctx._M_column += fprintf(stderr, "%u", _M_line);
1117 print_literal(ctx, ":");
1118 go_to_next_line = true;
1119 }
1120
1121 if (go_to_next_line)
1122 print_literal(ctx, "\n");
1123
1124 if (ctx._M_max_length)
1125 ctx._M_wordwrap = true;
1126
1127 if (_M_function)
1128 {
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");
1134 }
1135
1136 print_literal(ctx, "Error: ");
1137
1138 // Print the error message
1139 assert(_M_text);
1140 print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters);
1141 print_literal(ctx, ".\n");
1142
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)
1148 {
1149 switch (_M_parameters[i]._M_kind)
1150 {
1151 case _Parameter::__iterator:
1152 case _Parameter::__sequence:
1153 case _Parameter::__instance:
1154 case _Parameter::__iterator_value_type:
1155 if (!has_header)
1156 {
1157 print_literal(ctx, "\nObjects involved in the operation:\n");
1158 has_header = true;
1159 }
1160 print_description(ctx, _M_parameters[i]);
1161 break;
1162
1163 default:
1164 break;
1165 }
1166 }
1167
1168 abort();
1169 }
1170
1171 #if !_GLIBCXX_INLINE_VERSION
1172 // Deprecated methods kept for backward compatibility.
1173 void
1174 _Error_formatter::_Parameter::_M_print_field(
1175 const _Error_formatter*, const char*) const
1176 { }
1177
1178 void
1179 _Error_formatter::_Parameter::_M_print_description(const _Error_formatter*) const
1180 { }
1181
1182 template<typename _Tp>
1183 void
1184 _Error_formatter::_M_format_word(char*, int, const char*, _Tp)
1185 const throw ()
1186 { }
1187
1188 void
1189 _Error_formatter::_M_print_word(const char*) const
1190 { }
1191
1192 void
1193 _Error_formatter::_M_print_string(const char*) const
1194 { }
1195
1196 void
1197 _Error_formatter::_M_get_max_length() const throw ()
1198 { }
1199
1200 // Instantiations.
1201 template
1202 void
1203 _Error_formatter::_M_format_word(char*, int, const char*,
1204 const void*) const;
1205
1206 template
1207 void
1208 _Error_formatter::_M_format_word(char*, int, const char*, long) const;
1209
1210 template
1211 void
1212 _Error_formatter::_M_format_word(char*, int, const char*,
1213 std::size_t) const;
1214
1215 template
1216 void
1217 _Error_formatter::_M_format_word(char*, int, const char*,
1218 const char*) const;
1219 #endif
1220
1221 } // namespace __gnu_debug