1 // Debugging mode support code -*- C++ -*- 2 3 // Copyright (C) 2003, 2004, 2005, 2006 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 #include <debug/debug.h> 32 #include <debug/safe_sequence.h> 33 #include <debug/safe_iterator.h> 34 #include <algorithm> 35 #include <cassert> 36 #include <cstring> 37 #include <cctype> 38 39 using namespace std; 40 41 namespace 42 { 43 __gnu_cxx::__mutex safe_base_mutex; 44 } // anonymous namespace 45 46 namespace __gnu_debug 47 { 48 static const char* _S_debug_messages[] = 49 { 50 "function requires a valid iterator range [%1.name;, %2.name;)", 51 "attempt to insert into container with a singular iterator", 52 "attempt to insert into container with an iterator" 53 " from a different container", 54 "attempt to erase from container with a %2.state; iterator", 55 "attempt to erase from container with an iterator" 56 " from a different container", 57 "attempt to subscript container with out-of-bounds index %2;," 58 " but container only holds %3; elements", 59 "attempt to access an element in an empty container", 60 "elements in iterator range [%1.name;, %2.name;)" 61 " are not partitioned by the value %3;", 62 "elements in iterator range [%1.name;, %2.name;)" 63 " are not partitioned by the predicate %3; and value %4;", 64 "elements in iterator range [%1.name;, %2.name;) are not sorted", 65 "elements in iterator range [%1.name;, %2.name;)" 66 " are not sorted according to the predicate %3;", 67 "elements in iterator range [%1.name;, %2.name;) do not form a heap", 68 "elements in iterator range [%1.name;, %2.name;)" 69 " do not form a heap with respect to the predicate %3;", 70 "attempt to write through a singular bitset reference", 71 "attempt to read from a singular bitset reference", 72 "attempt to flip a singular bitset reference", 73 "attempt to splice a list into itself", 74 "attempt to splice lists with inequal allocators", 75 "attempt to splice elements referenced by a %1.state; iterator", 76 "attempt to splice an iterator from a different container", 77 "splice destination %1.name;" 78 " occurs within source range [%2.name;, %3.name;)", 79 "attempt to initialize an iterator that will immediately become singular", 80 "attempt to copy-construct an iterator from a singular iterator", 81 "attempt to construct a constant iterator" 82 " from a singular mutable iterator", 83 "attempt to copy from a singular iterator", 84 "attempt to dereference a %1.state; iterator", 85 "attempt to increment a %1.state; iterator", 86 "attempt to decrement a %1.state; iterator", 87 "attempt to subscript a %1.state; iterator %2; step from" 88 " its current position, which falls outside its dereferenceable range", 89 "attempt to advance a %1.state; iterator %2; steps," 90 " which falls outside its valid range", 91 "attempt to retreat a %1.state; iterator %2; steps," 92 " which falls outside its valid range", 93 "attempt to compare a %1.state; iterator to a %2.state; iterator", 94 "attempt to compare iterators from different sequences", 95 "attempt to order a %1.state; iterator to a %2.state; iterator", 96 "attempt to order iterators from different sequences", 97 "attempt to compute the difference between a %1.state;" 98 " iterator to a %2.state; iterator", 99 "attempt to compute the different between two iterators" 100 " from different sequences", 101 "attempt to dereference an end-of-stream istream_iterator", 102 "attempt to increment an end-of-stream istream_iterator", 103 "attempt to output via an ostream_iterator with no associated stream", 104 "attempt to dereference an end-of-stream istreambuf_iterator" 105 " (this is a GNU extension)", 106 "attempt to increment an end-of-stream istreambuf_iterator" 107 }; 108 109 void 110 _Safe_sequence_base:: 111 _M_detach_all() 112 { 113 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 114 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 115 { 116 _Safe_iterator_base* __old = __iter; 117 __iter = __iter->_M_next; 118 __old->_M_detach_single(); 119 } 120 121 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 122 { 123 _Safe_iterator_base* __old = __iter2; 124 __iter2 = __iter2->_M_next; 125 __old->_M_detach_single(); 126 } 127 } 128 129 void 130 _Safe_sequence_base:: 131 _M_detach_singular() 132 { 133 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 134 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 135 { 136 _Safe_iterator_base* __old = __iter; 137 __iter = __iter->_M_next; 138 if (__old->_M_singular()) 139 __old->_M_detach_single(); 140 } 141 142 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 143 { 144 _Safe_iterator_base* __old = __iter2; 145 __iter2 = __iter2->_M_next; 146 if (__old->_M_singular()) 147 __old->_M_detach_single(); 148 } 149 } 150 151 void 152 _Safe_sequence_base:: 153 _M_revalidate_singular() 154 { 155 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 156 for (_Safe_iterator_base* __iter = _M_iterators; __iter; 157 __iter = __iter->_M_next) 158 __iter->_M_version = _M_version; 159 160 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 161 __iter2 = __iter2->_M_next) 162 __iter2->_M_version = _M_version; 163 } 164 165 void 166 _Safe_sequence_base:: 167 _M_swap(_Safe_sequence_base& __x) 168 { 169 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 170 swap(_M_iterators, __x._M_iterators); 171 swap(_M_const_iterators, __x._M_const_iterators); 172 swap(_M_version, __x._M_version); 173 _Safe_iterator_base* __iter; 174 for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 175 __iter->_M_sequence = this; 176 for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next) 177 __iter->_M_sequence = &__x; 178 for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 179 __iter->_M_sequence = this; 180 for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next) 181 __iter->_M_sequence = &__x; 182 } 183 184 __gnu_cxx::__mutex& 185 _Safe_sequence_base:: 186 _M_get_mutex() 187 { return safe_base_mutex; } 188 189 void 190 _Safe_iterator_base:: 191 _M_attach(_Safe_sequence_base* __seq, bool __constant) 192 { 193 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 194 _M_attach_single(__seq, __constant); 195 } 196 197 void 198 _Safe_iterator_base:: 199 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) 200 { 201 _M_detach_single(); 202 203 // Attach to the new sequence (if there is one) 204 if (__seq) 205 { 206 _M_sequence = __seq; 207 _M_version = _M_sequence->_M_version; 208 _M_prior = 0; 209 if (__constant) 210 { 211 _M_next = _M_sequence->_M_const_iterators; 212 if (_M_next) 213 _M_next->_M_prior = this; 214 _M_sequence->_M_const_iterators = this; 215 } 216 else 217 { 218 _M_next = _M_sequence->_M_iterators; 219 if (_M_next) 220 _M_next->_M_prior = this; 221 _M_sequence->_M_iterators = this; 222 } 223 } 224 } 225 226 void 227 _Safe_iterator_base:: 228 _M_detach() 229 { 230 __gnu_cxx::__scoped_lock sentry(safe_base_mutex); 231 _M_detach_single(); 232 } 233 234 void 235 _Safe_iterator_base:: 236 _M_detach_single() 237 { 238 if (_M_sequence) 239 { 240 // Remove us from this sequence's list 241 if (_M_prior) 242 _M_prior->_M_next = _M_next; 243 if (_M_next) 244 _M_next->_M_prior = _M_prior; 245 246 if (_M_sequence->_M_const_iterators == this) 247 _M_sequence->_M_const_iterators = _M_next; 248 if (_M_sequence->_M_iterators == this) 249 _M_sequence->_M_iterators = _M_next; 250 } 251 252 _M_sequence = 0; 253 _M_version = 0; 254 _M_prior = 0; 255 _M_next = 0; 256 } 257 258 bool 259 _Safe_iterator_base:: 260 _M_singular() const 261 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 262 263 bool 264 _Safe_iterator_base:: 265 _M_can_compare(const _Safe_iterator_base& __x) const 266 { 267 return (!_M_singular() 268 && !__x._M_singular() && _M_sequence == __x._M_sequence); 269 } 270 271 __gnu_cxx::__mutex& 272 _Safe_iterator_base:: 273 _M_get_mutex() 274 { return safe_base_mutex; } 275 276 void 277 _Error_formatter::_Parameter:: 278 _M_print_field(const _Error_formatter* __formatter, const char* __name) const 279 { 280 assert(this->_M_kind != _Parameter::__unused_param); 281 const int __bufsize = 64; 282 char __buf[__bufsize]; 283 284 if (_M_kind == __iterator) 285 { 286 if (strcmp(__name, "name") == 0) 287 { 288 assert(_M_variant._M_iterator._M_name); 289 __formatter->_M_print_word(_M_variant._M_iterator._M_name); 290 } 291 else if (strcmp(__name, "address") == 0) 292 { 293 __formatter->_M_format_word(__buf, __bufsize, "%p", 294 _M_variant._M_iterator._M_address); 295 __formatter->_M_print_word(__buf); 296 } 297 else if (strcmp(__name, "type") == 0) 298 { 299 assert(_M_variant._M_iterator._M_type); 300 // TBD: demangle! 301 __formatter->_M_print_word(_M_variant._M_iterator._M_type->name()); 302 } 303 else if (strcmp(__name, "constness") == 0) 304 { 305 static const char* __constness_names[__last_constness] = 306 { 307 "<unknown>", 308 "constant", 309 "mutable" 310 }; 311 __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]); 312 } 313 else if (strcmp(__name, "state") == 0) 314 { 315 static const char* __state_names[__last_state] = 316 { 317 "<unknown>", 318 "singular", 319 "dereferenceable (start-of-sequence)", 320 "dereferenceable", 321 "past-the-end" 322 }; 323 __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]); 324 } 325 else if (strcmp(__name, "sequence") == 0) 326 { 327 assert(_M_variant._M_iterator._M_sequence); 328 __formatter->_M_format_word(__buf, __bufsize, "%p", 329 _M_variant._M_iterator._M_sequence); 330 __formatter->_M_print_word(__buf); 331 } 332 else if (strcmp(__name, "seq_type") == 0) 333 { 334 // TBD: demangle! 335 assert(_M_variant._M_iterator._M_seq_type); 336 __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name()); 337 } 338 else 339 assert(false); 340 } 341 else if (_M_kind == __sequence) 342 { 343 if (strcmp(__name, "name") == 0) 344 { 345 assert(_M_variant._M_sequence._M_name); 346 __formatter->_M_print_word(_M_variant._M_sequence._M_name); 347 } 348 else if (strcmp(__name, "address") == 0) 349 { 350 assert(_M_variant._M_sequence._M_address); 351 __formatter->_M_format_word(__buf, __bufsize, "%p", 352 _M_variant._M_sequence._M_address); 353 __formatter->_M_print_word(__buf); 354 } 355 else if (strcmp(__name, "type") == 0) 356 { 357 // TBD: demangle! 358 assert(_M_variant._M_sequence._M_type); 359 __formatter->_M_print_word(_M_variant._M_sequence._M_type->name()); 360 } 361 else 362 assert(false); 363 } 364 else if (_M_kind == __integer) 365 { 366 if (strcmp(__name, "name") == 0) 367 { 368 assert(_M_variant._M_integer._M_name); 369 __formatter->_M_print_word(_M_variant._M_integer._M_name); 370 } 371 else 372 assert(false); 373 } 374 else if (_M_kind == __string) 375 { 376 if (strcmp(__name, "name") == 0) 377 { 378 assert(_M_variant._M_string._M_name); 379 __formatter->_M_print_word(_M_variant._M_string._M_name); 380 } 381 else 382 assert(false); 383 } 384 else 385 { 386 assert(false); 387 } 388 } 389 390 void 391 _Error_formatter::_Parameter:: 392 _M_print_description(const _Error_formatter* __formatter) const 393 { 394 const int __bufsize = 128; 395 char __buf[__bufsize]; 396 397 if (_M_kind == __iterator) 398 { 399 __formatter->_M_print_word("iterator "); 400 if (_M_variant._M_iterator._M_name) 401 { 402 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 403 _M_variant._M_iterator._M_name); 404 __formatter->_M_print_word(__buf); 405 } 406 407 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 408 _M_variant._M_iterator._M_address); 409 __formatter->_M_print_word(__buf); 410 if (_M_variant._M_iterator._M_type) 411 { 412 __formatter->_M_print_word("type = "); 413 _M_print_field(__formatter, "type"); 414 415 if (_M_variant._M_iterator._M_constness != __unknown_constness) 416 { 417 __formatter->_M_print_word(" ("); 418 _M_print_field(__formatter, "constness"); 419 __formatter->_M_print_word(" iterator)"); 420 } 421 __formatter->_M_print_word(";\n"); 422 } 423 424 if (_M_variant._M_iterator._M_state != __unknown_state) 425 { 426 __formatter->_M_print_word(" state = "); 427 _M_print_field(__formatter, "state"); 428 __formatter->_M_print_word(";\n"); 429 } 430 431 if (_M_variant._M_iterator._M_sequence) 432 { 433 __formatter->_M_print_word(" references sequence "); 434 if (_M_variant._M_iterator._M_seq_type) 435 { 436 __formatter->_M_print_word("with type `"); 437 _M_print_field(__formatter, "seq_type"); 438 __formatter->_M_print_word("' "); 439 } 440 441 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 442 _M_variant._M_sequence._M_address); 443 __formatter->_M_print_word(__buf); 444 } 445 __formatter->_M_print_word("}\n"); 446 } 447 else if (_M_kind == __sequence) 448 { 449 __formatter->_M_print_word("sequence "); 450 if (_M_variant._M_sequence._M_name) 451 { 452 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 453 _M_variant._M_sequence._M_name); 454 __formatter->_M_print_word(__buf); 455 } 456 457 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 458 _M_variant._M_sequence._M_address); 459 __formatter->_M_print_word(__buf); 460 461 if (_M_variant._M_sequence._M_type) 462 { 463 __formatter->_M_print_word(" type = "); 464 _M_print_field(__formatter, "type"); 465 __formatter->_M_print_word(";\n"); 466 } 467 __formatter->_M_print_word("}\n"); 468 } 469 } 470 471 const _Error_formatter& 472 _Error_formatter::_M_message(_Debug_msg_id __id) const 473 { return this->_M_message(_S_debug_messages[__id]); } 474 475 void 476 _Error_formatter::_M_error() const 477 { 478 const int __bufsize = 128; 479 char __buf[__bufsize]; 480 481 // Emit file & line number information 482 _M_column = 1; 483 _M_wordwrap = false; 484 if (_M_file) 485 { 486 _M_format_word(__buf, __bufsize, "%s:", _M_file); 487 _M_print_word(__buf); 488 _M_column += strlen(__buf); 489 } 490 491 if (_M_line > 0) 492 { 493 _M_format_word(__buf, __bufsize, "%u:", _M_line); 494 _M_print_word(__buf); 495 _M_column += strlen(__buf); 496 } 497 498 _M_wordwrap = true; 499 _M_print_word("error: "); 500 501 // Print the error message 502 assert(_M_text); 503 _M_print_string(_M_text); 504 _M_print_word(".\n"); 505 506 // Emit descriptions of the objects involved in the operation 507 _M_wordwrap = false; 508 bool __has_noninteger_parameters = false; 509 for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 510 { 511 if (_M_parameters[__i]._M_kind == _Parameter::__iterator 512 || _M_parameters[__i]._M_kind == _Parameter::__sequence) 513 { 514 if (!__has_noninteger_parameters) 515 { 516 _M_first_line = true; 517 _M_print_word("\nObjects involved in the operation:\n"); 518 __has_noninteger_parameters = true; 519 } 520 _M_parameters[__i]._M_print_description(this); 521 } 522 } 523 524 abort(); 525 } 526 527 template<typename _Tp> 528 void 529 _Error_formatter::_M_format_word(char* __buf, 530 int __n __attribute__ ((__unused__)), 531 const char* __fmt, _Tp __s) const 532 { 533 #ifdef _GLIBCXX_USE_C99 534 std::snprintf(__buf, __n, __fmt, __s); 535 #else 536 std::sprintf(__buf, __fmt, __s); 537 #endif 538 } 539 540 541 void 542 _Error_formatter::_M_print_word(const char* __word) const 543 { 544 if (!_M_wordwrap) 545 { 546 fprintf(stderr, "%s", __word); 547 return; 548 } 549 550 size_t __length = strlen(__word); 551 if (__length == 0) 552 return; 553 554 if ((_M_column + __length < _M_max_length) 555 || (__length >= _M_max_length && _M_column == 1)) 556 { 557 // If this isn't the first line, indent 558 if (_M_column == 1 && !_M_first_line) 559 { 560 char __spacing[_M_indent + 1]; 561 for (int i = 0; i < _M_indent; ++i) 562 __spacing[i] = ' '; 563 __spacing[_M_indent] = '\0'; 564 fprintf(stderr, "%s", __spacing); 565 _M_column += _M_indent; 566 } 567 568 fprintf(stderr, "%s", __word); 569 _M_column += __length; 570 571 if (__word[__length - 1] == '\n') 572 { 573 _M_first_line = false; 574 _M_column = 1; 575 } 576 } 577 else 578 { 579 _M_column = 1; 580 _M_print_word("\n"); 581 _M_print_word(__word); 582 } 583 } 584 585 void 586 _Error_formatter:: 587 _M_print_string(const char* __string) const 588 { 589 const char* __start = __string; 590 const char* __finish = __start; 591 const int __bufsize = 128; 592 char __buf[__bufsize]; 593 594 while (*__start) 595 { 596 if (*__start != '%') 597 { 598 // [__start, __finish) denotes the next word 599 __finish = __start; 600 while (isalnum(*__finish)) 601 ++__finish; 602 if (__start == __finish) 603 ++__finish; 604 if (isspace(*__finish)) 605 ++__finish; 606 607 const ptrdiff_t __len = __finish - __start; 608 assert(__len < __bufsize); 609 memcpy(__buf, __start, __len); 610 __buf[__len] = '\0'; 611 _M_print_word(__buf); 612 __start = __finish; 613 614 // Skip extra whitespace 615 while (*__start == ' ') 616 ++__start; 617 618 continue; 619 } 620 621 ++__start; 622 assert(*__start); 623 if (*__start == '%') 624 { 625 _M_print_word("%"); 626 ++__start; 627 continue; 628 } 629 630 // Get the parameter number 631 assert(*__start >= '1' && *__start <= '9'); 632 size_t __param = *__start - '0'; 633 --__param; 634 assert(__param < _M_num_parameters); 635 636 // '.' separates the parameter number from the field 637 // name, if there is one. 638 ++__start; 639 if (*__start != '.') 640 { 641 assert(*__start == ';'); 642 ++__start; 643 __buf[0] = '\0'; 644 if (_M_parameters[__param]._M_kind == _Parameter::__integer) 645 { 646 _M_format_word(__buf, __bufsize, "%ld", 647 _M_parameters[__param]._M_variant._M_integer._M_value); 648 _M_print_word(__buf); 649 } 650 else if (_M_parameters[__param]._M_kind == _Parameter::__string) 651 _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 652 continue; 653 } 654 655 // Extract the field name we want 656 enum { __max_field_len = 16 }; 657 char __field[__max_field_len]; 658 int __field_idx = 0; 659 ++__start; 660 while (*__start != ';') 661 { 662 assert(*__start); 663 assert(__field_idx < __max_field_len-1); 664 __field[__field_idx++] = *__start++; 665 } 666 ++__start; 667 __field[__field_idx] = 0; 668 669 _M_parameters[__param]._M_print_field(this, __field); 670 } 671 } 672 673 // Instantiations. 674 template 675 void 676 _Error_formatter::_M_format_word(char*, int, const char*, 677 const void*) const; 678 679 template 680 void 681 _Error_formatter::_M_format_word(char*, int, const char*, long) const; 682 683 template 684 void 685 _Error_formatter::_M_format_word(char*, int, const char*, 686 std::size_t) const; 687 688 template 689 void 690 _Error_formatter::_M_format_word(char*, int, const char*, 691 const char*) const; 692 } // namespace __gnu_debug 693