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