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