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