1// Debug-mode error formatting implementation -*- C++ -*- 2 3// Copyright (C) 2003-2022 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file debug/formatter.h 26 * This file is a GNU debug extension to the Standard C++ Library. 27 */ 28 29#ifndef _GLIBCXX_DEBUG_FORMATTER_H 30#define _GLIBCXX_DEBUG_FORMATTER_H 1 31 32#include <bits/c++config.h> 33 34#if __cpp_rtti 35# include <typeinfo> 36# define _GLIBCXX_TYPEID(_Type) &typeid(_Type) 37#else 38namespace std 39{ 40 class type_info; 41} 42# define _GLIBCXX_TYPEID(_Type) 0 43#endif 44 45#if __cplusplus >= 201103L 46namespace __gnu_cxx 47{ 48_GLIBCXX_BEGIN_NAMESPACE_VERSION 49 50template<typename _Iterator, typename _Container> 51 class __normal_iterator; 52 53_GLIBCXX_END_NAMESPACE_VERSION 54} 55 56namespace std 57{ 58_GLIBCXX_BEGIN_NAMESPACE_VERSION 59 60template<typename _Iterator> 61 class reverse_iterator; 62 63template<typename _Iterator> 64 class move_iterator; 65 66_GLIBCXX_END_NAMESPACE_VERSION 67} 68#endif 69 70namespace __gnu_debug 71{ 72 using std::type_info; 73 74 template<typename _Iterator> 75 _GLIBCXX_CONSTEXPR 76 bool __check_singular(_Iterator const&); 77 78 class _Safe_sequence_base; 79 80 template<typename _Iterator, typename _Sequence, typename _Category> 81 class _Safe_iterator; 82 83 template<typename _Iterator, typename _Sequence> 84 class _Safe_local_iterator; 85 86 template<typename _Sequence> 87 class _Safe_sequence; 88 89 enum _Debug_msg_id 90 { 91 // General checks 92 __msg_valid_range, 93 __msg_insert_singular, 94 __msg_insert_different, 95 __msg_erase_bad, 96 __msg_erase_different, 97 __msg_subscript_oob, 98 __msg_empty, 99 __msg_unpartitioned, 100 __msg_unpartitioned_pred, 101 __msg_unsorted, 102 __msg_unsorted_pred, 103 __msg_not_heap, 104 __msg_not_heap_pred, 105 // std::bitset checks 106 __msg_bad_bitset_write, 107 __msg_bad_bitset_read, 108 __msg_bad_bitset_flip, 109 // std::list checks 110 __msg_self_splice, 111 __msg_splice_alloc, 112 __msg_splice_bad, 113 __msg_splice_other, 114 __msg_splice_overlap, 115 // iterator checks 116 __msg_init_singular, 117 __msg_init_copy_singular, 118 __msg_init_const_singular, 119 __msg_copy_singular, 120 __msg_bad_deref, 121 __msg_bad_inc, 122 __msg_bad_dec, 123 __msg_iter_subscript_oob, 124 __msg_advance_oob, 125 __msg_retreat_oob, 126 __msg_iter_compare_bad, 127 __msg_compare_different, 128 __msg_iter_order_bad, 129 __msg_order_different, 130 __msg_distance_bad, 131 __msg_distance_different, 132 // istream_iterator 133 __msg_deref_istream, 134 __msg_inc_istream, 135 // ostream_iterator 136 __msg_output_ostream, 137 // istreambuf_iterator 138 __msg_deref_istreambuf, 139 __msg_inc_istreambuf, 140 // forward_list 141 __msg_insert_after_end, 142 __msg_erase_after_bad, 143 __msg_valid_range2, 144 // unordered container local iterators 145 __msg_local_iter_compare_bad, 146 __msg_non_empty_range, 147 // self move assign (no longer used) 148 __msg_self_move_assign, 149 // unordered container buckets 150 __msg_bucket_index_oob, 151 __msg_valid_load_factor, 152 // others 153 __msg_equal_allocs, 154 __msg_insert_range_from_self, 155 __msg_irreflexive_ordering 156 }; 157 158 class _Error_formatter 159 { 160 // Tags denoting the type of parameter for construction 161 struct _Is_iterator { }; 162 struct _Is_iterator_value_type { }; 163 struct _Is_sequence { }; 164 struct _Is_instance { }; 165 166 public: 167 /// Whether an iterator is constant, mutable, or unknown 168 enum _Constness 169 { 170 __unknown_constness, 171 __const_iterator, 172 __mutable_iterator, 173 __last_constness 174 }; 175 176 // The state of the iterator (fine-grained), if we know it. 177 enum _Iterator_state 178 { 179 __unknown_state, 180 __singular, // singular, may still be attached to a sequence 181 __begin, // dereferenceable, and at the beginning 182 __middle, // dereferenceable, not at the beginning 183 __end, // past-the-end, may be at beginning if sequence empty 184 __before_begin, // before begin 185 __rbegin, // dereferenceable, and at the reverse-beginning 186 __rmiddle, // reverse-dereferenceable, not at the reverse-beginning 187 __rend, // reverse-past-the-end 188 __last_state 189 }; 190 191 // A parameter that may be referenced by an error message 192 struct _Parameter 193 { 194 enum 195 { 196 __unused_param, 197 __iterator, 198 __sequence, 199 __integer, 200 __string, 201 __instance, 202 __iterator_value_type 203 } _M_kind; 204 205 struct _Named 206 { 207 const char* _M_name; 208 }; 209 210 struct _Type : _Named 211 { 212 const type_info* _M_type; 213 }; 214 215 struct _Instance : _Type 216 { 217 const void* _M_address; 218 }; 219 220 union 221 { 222 // When _M_kind == __iterator 223 struct : _Instance 224 { 225 _Constness _M_constness; 226 _Iterator_state _M_state; 227 const void* _M_sequence; 228 const type_info* _M_seq_type; 229 } _M_iterator; 230 231 // When _M_kind == __sequence 232 _Instance _M_sequence; 233 234 // When _M_kind == __integer 235 struct : _Named 236 { 237 long _M_value; 238 } _M_integer; 239 240 // When _M_kind == __string 241 struct : _Named 242 { 243 const char* _M_value; 244 } _M_string; 245 246 // When _M_kind == __instance 247 _Instance _M_instance; 248 249 // When _M_kind == __iterator_value_type 250 _Type _M_iterator_value_type; 251 } _M_variant; 252 253 _Parameter() : _M_kind(__unused_param), _M_variant() { } 254 255 _Parameter(long __value, const char* __name) 256 : _M_kind(__integer), _M_variant() 257 { 258 _M_variant._M_integer._M_name = __name; 259 _M_variant._M_integer._M_value = __value; 260 } 261 262 _Parameter(const char* __value, const char* __name) 263 : _M_kind(__string), _M_variant() 264 { 265 _M_variant._M_string._M_name = __name; 266 _M_variant._M_string._M_value = __value; 267 } 268 269 template<typename _Iterator, typename _Sequence, typename _Category> 270 _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it, 271 const char* __name, _Is_iterator) 272 : _M_kind(__iterator), _M_variant() 273 { 274 _M_variant._M_iterator._M_name = __name; 275 _M_variant._M_iterator._M_address = std::__addressof(__it); 276 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); 277 _M_variant._M_iterator._M_constness = 278 __it._S_constant() ? __const_iterator : __mutable_iterator; 279 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 280 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 281 282 if (__it._M_singular()) 283 _M_variant._M_iterator._M_state = __singular; 284 else 285 { 286 if (__it._M_is_before_begin()) 287 _M_variant._M_iterator._M_state = __before_begin; 288 else if (__it._M_is_end()) 289 _M_variant._M_iterator._M_state = __end; 290 else if (__it._M_is_begin()) 291 _M_variant._M_iterator._M_state = __begin; 292 else 293 _M_variant._M_iterator._M_state = __middle; 294 } 295 } 296 297 template<typename _Iterator, typename _Sequence> 298 _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, 299 const char* __name, _Is_iterator) 300 : _M_kind(__iterator), _M_variant() 301 { 302 _M_variant._M_iterator._M_name = __name; 303 _M_variant._M_iterator._M_address = std::__addressof(__it); 304 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); 305 _M_variant._M_iterator._M_constness = 306 __it._S_constant() ? __const_iterator : __mutable_iterator; 307 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 308 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 309 310 if (__it._M_singular()) 311 _M_variant._M_iterator._M_state = __singular; 312 else 313 { 314 if (__it._M_is_end()) 315 _M_variant._M_iterator._M_state = __end; 316 else if (__it._M_is_begin()) 317 _M_variant._M_iterator._M_state = __begin; 318 else 319 _M_variant._M_iterator._M_state = __middle; 320 } 321 } 322 323 template<typename _Type> 324 _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) 325 : _M_kind(__iterator), _M_variant() 326 { 327 _M_variant._M_iterator._M_name = __name; 328 _M_variant._M_iterator._M_address = std::__addressof(__it); 329 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 330 _M_variant._M_iterator._M_constness = __const_iterator; 331 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 332 _M_variant._M_iterator._M_sequence = 0; 333 _M_variant._M_iterator._M_seq_type = 0; 334 } 335 336 template<typename _Type> 337 _Parameter(_Type* const& __it, const char* __name, _Is_iterator) 338 : _M_kind(__iterator), _M_variant() 339 { 340 _M_variant._M_iterator._M_name = __name; 341 _M_variant._M_iterator._M_address = std::__addressof(__it); 342 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 343 _M_variant._M_iterator._M_constness = __mutable_iterator; 344 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 345 _M_variant._M_iterator._M_sequence = 0; 346 _M_variant._M_iterator._M_seq_type = 0; 347 } 348 349 template<typename _Iterator> 350 _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) 351 : _M_kind(__iterator), _M_variant() 352 { 353 _M_variant._M_iterator._M_name = __name; 354 _M_variant._M_iterator._M_address = std::__addressof(__it); 355 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 356 _M_variant._M_iterator._M_constness = __unknown_constness; 357 _M_variant._M_iterator._M_state = 358 __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; 359 _M_variant._M_iterator._M_sequence = 0; 360 _M_variant._M_iterator._M_seq_type = 0; 361 } 362 363#if __cplusplus >= 201103L 364 // The following constructors are only defined in C++11 to take 365 // advantage of the constructor delegation feature. 366 template<typename _Iterator, typename _Container> 367 _Parameter( 368 __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it, 369 const char* __name, _Is_iterator) 370 : _Parameter(__it.base(), __name, _Is_iterator{}) 371 { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } 372 373 template<typename _Iterator> 374 _Parameter(std::reverse_iterator<_Iterator> const& __it, 375 const char* __name, _Is_iterator) 376 : _Parameter(__it.base(), __name, _Is_iterator{}) 377 { 378 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 379 _M_variant._M_iterator._M_state 380 = _S_reverse_state(_M_variant._M_iterator._M_state); 381 } 382 383 template<typename _Iterator, typename _Sequence, typename _Category> 384 _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence, 385 _Category>> const& __it, 386 const char* __name, _Is_iterator) 387 : _Parameter(__it.base(), __name, _Is_iterator{}) 388 { 389 _M_variant._M_iterator._M_type 390 = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>); 391 _M_variant._M_iterator._M_state 392 = _S_reverse_state(_M_variant._M_iterator._M_state); 393 } 394 395 template<typename _Iterator> 396 _Parameter(std::move_iterator<_Iterator> const& __it, 397 const char* __name, _Is_iterator) 398 : _Parameter(__it.base(), __name, _Is_iterator{}) 399 { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } 400 401 template<typename _Iterator, typename _Sequence, typename _Category> 402 _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence, 403 _Category>> const& __it, 404 const char* __name, _Is_iterator) 405 : _Parameter(__it.base(), __name, _Is_iterator{}) 406 { 407 _M_variant._M_iterator._M_type 408 = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>); 409 } 410 411 private: 412 _Iterator_state 413 _S_reverse_state(_Iterator_state __state) 414 { 415 switch (__state) 416 { 417 case __begin: 418 return __rend; 419 case __middle: 420 return __rmiddle; 421 case __end: 422 return __rbegin; 423 default: 424 return __state; 425 } 426 } 427 428 public: 429#endif 430 431 template<typename _Sequence> 432 _Parameter(const _Safe_sequence<_Sequence>& __seq, 433 const char* __name, _Is_sequence) 434 : _M_kind(__sequence), _M_variant() 435 { 436 _M_variant._M_sequence._M_name = __name; 437 _M_variant._M_sequence._M_address = 438 static_cast<const _Sequence*>(std::__addressof(__seq)); 439 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 440 } 441 442 template<typename _Sequence> 443 _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 444 : _M_kind(__sequence), _M_variant() 445 { 446 _M_variant._M_sequence._M_name = __name; 447 _M_variant._M_sequence._M_address = std::__addressof(__seq); 448 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 449 } 450 451 template<typename _Iterator> 452 _Parameter(const _Iterator& __it, const char* __name, 453 _Is_iterator_value_type) 454 : _M_kind(__iterator_value_type), _M_variant() 455 { 456 _M_variant._M_iterator_value_type._M_name = __name; 457 _M_variant._M_iterator_value_type._M_type = 458 _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); 459 } 460 461 template<typename _Type> 462 _Parameter(const _Type& __inst, const char* __name, _Is_instance) 463 : _M_kind(__instance), _M_variant() 464 { 465 _M_variant._M_instance._M_name = __name; 466 _M_variant._M_instance._M_address = &__inst; 467 _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); 468 } 469 470#if !_GLIBCXX_INLINE_VERSION 471 void 472 _M_print_field(const _Error_formatter* __formatter, 473 const char* __name) const _GLIBCXX_DEPRECATED; 474 475 void 476 _M_print_description(const _Error_formatter* __formatter) 477 const _GLIBCXX_DEPRECATED; 478#endif 479 }; 480 481 template<typename _Iterator> 482 _Error_formatter& 483 _M_iterator(const _Iterator& __it, const char* __name = 0) 484 { 485 if (_M_num_parameters < std::size_t(__max_parameters)) 486 _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 487 _Is_iterator()); 488 return *this; 489 } 490 491 template<typename _Iterator> 492 _Error_formatter& 493 _M_iterator_value_type(const _Iterator& __it, 494 const char* __name = 0) 495 { 496 if (_M_num_parameters < __max_parameters) 497 _M_parameters[_M_num_parameters++] = 498 _Parameter(__it, __name, _Is_iterator_value_type()); 499 return *this; 500 } 501 502 _Error_formatter& 503 _M_integer(long __value, const char* __name = 0) 504 { 505 if (_M_num_parameters < __max_parameters) 506 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 507 return *this; 508 } 509 510 _Error_formatter& 511 _M_string(const char* __value, const char* __name = 0) 512 { 513 if (_M_num_parameters < __max_parameters) 514 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 515 return *this; 516 } 517 518 template<typename _Sequence> 519 _Error_formatter& 520 _M_sequence(const _Sequence& __seq, const char* __name = 0) 521 { 522 if (_M_num_parameters < __max_parameters) 523 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 524 _Is_sequence()); 525 return *this; 526 } 527 528 template<typename _Type> 529 _Error_formatter& 530 _M_instance(const _Type& __inst, const char* __name = 0) 531 { 532 if (_M_num_parameters < __max_parameters) 533 _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, 534 _Is_instance()); 535 return *this; 536 } 537 538 _Error_formatter& 539 _M_message(const char* __text) 540 { _M_text = __text; return *this; } 541 542 // Kept const qualifier for backward compatibility, to keep the same 543 // exported symbol. 544 _Error_formatter& 545 _M_message(_Debug_msg_id __id) const throw (); 546 547 _GLIBCXX_NORETURN void 548 _M_error() const; 549 550#if !_GLIBCXX_INLINE_VERSION 551 template<typename _Tp> 552 void 553 _M_format_word(char*, int, const char*, _Tp) 554 const throw () _GLIBCXX_DEPRECATED; 555 556 void 557 _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; 558 559 void 560 _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; 561#endif 562 563 private: 564 _Error_formatter(const char* __file, unsigned int __line, 565 const char* __function) 566 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) 567 , _M_function(__function) 568 { } 569 570#if !_GLIBCXX_INLINE_VERSION 571 void 572 _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; 573#endif 574 575 enum { __max_parameters = 9 }; 576 577 const char* _M_file; 578 unsigned int _M_line; 579 _Parameter _M_parameters[__max_parameters]; 580 unsigned int _M_num_parameters; 581 const char* _M_text; 582 const char* _M_function; 583 584 public: 585 static _Error_formatter& 586 _S_at(const char* __file, unsigned int __line, const char* __function) 587 { 588 static _Error_formatter __formatter(__file, __line, __function); 589 return __formatter; 590 } 591 }; 592} // namespace __gnu_debug 593 594#undef _GLIBCXX_TYPEID 595 596#endif 597