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