1 // Debug-mode error formatting implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2019 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 _M_variant._M_iterator._M_constness = 304 __it._S_constant() ? __const_iterator : __mutable_iterator; 305 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 306 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 307 308 if (__it._M_singular()) 309 _M_variant._M_iterator._M_state = __singular; 310 else 311 { 312 if (__it._M_is_end()) 313 _M_variant._M_iterator._M_state = __end; 314 else if (__it._M_is_begin()) 315 _M_variant._M_iterator._M_state = __begin; 316 else 317 _M_variant._M_iterator._M_state = __middle; 318 } 319 } 320 321 template<typename _Type> _Parameter_Parameter322 _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) 323 : _M_kind(__iterator), _M_variant() 324 { 325 _M_variant._M_iterator._M_name = __name; 326 _M_variant._M_iterator._M_address = std::__addressof(__it); 327 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 328 _M_variant._M_iterator._M_constness = __const_iterator; 329 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 330 _M_variant._M_iterator._M_sequence = 0; 331 _M_variant._M_iterator._M_seq_type = 0; 332 } 333 334 template<typename _Type> _Parameter_Parameter335 _Parameter(_Type* const& __it, const char* __name, _Is_iterator) 336 : _M_kind(__iterator), _M_variant() 337 { 338 _M_variant._M_iterator._M_name = __name; 339 _M_variant._M_iterator._M_address = std::__addressof(__it); 340 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 341 _M_variant._M_iterator._M_constness = __mutable_iterator; 342 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 343 _M_variant._M_iterator._M_sequence = 0; 344 _M_variant._M_iterator._M_seq_type = 0; 345 } 346 347 template<typename _Iterator> _Parameter_Parameter348 _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) 349 : _M_kind(__iterator), _M_variant() 350 { 351 _M_variant._M_iterator._M_name = __name; 352 _M_variant._M_iterator._M_address = std::__addressof(__it); 353 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 354 _M_variant._M_iterator._M_constness = __unknown_constness; 355 _M_variant._M_iterator._M_state = 356 __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; 357 _M_variant._M_iterator._M_sequence = 0; 358 _M_variant._M_iterator._M_seq_type = 0; 359 } 360 361 #if __cplusplus >= 201103L 362 // The following constructors are only defined in C++11 to take 363 // advantage of the constructor delegation feature. 364 template<typename _Iterator, typename _Container> _Parameter_Parameter365 _Parameter( 366 __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it, 367 const char* __name, _Is_iterator) 368 : _Parameter(__it.base(), __name, _Is_iterator{}) 369 { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } 370 371 template<typename _Iterator> _Parameter_Parameter372 _Parameter(std::reverse_iterator<_Iterator> const& __it, 373 const char* __name, _Is_iterator) 374 : _Parameter(__it.base(), __name, _Is_iterator{}) 375 { 376 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 377 _M_variant._M_iterator._M_state 378 = _S_reverse_state(_M_variant._M_iterator._M_state); 379 } 380 381 template<typename _Iterator, typename _Sequence, typename _Category> _Parameter_Parameter382 _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence, 383 _Category>> const& __it, 384 const char* __name, _Is_iterator) 385 : _Parameter(__it.base(), __name, _Is_iterator{}) 386 { 387 _M_variant._M_iterator._M_type 388 = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>); 389 _M_variant._M_iterator._M_state 390 = _S_reverse_state(_M_variant._M_iterator._M_state); 391 } 392 393 template<typename _Iterator> _Parameter_Parameter394 _Parameter(std::move_iterator<_Iterator> const& __it, 395 const char* __name, _Is_iterator) 396 : _Parameter(__it.base(), __name, _Is_iterator{}) 397 { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } 398 399 template<typename _Iterator, typename _Sequence, typename _Category> _Parameter_Parameter400 _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence, 401 _Category>> const& __it, 402 const char* __name, _Is_iterator) 403 : _Parameter(__it.base(), __name, _Is_iterator{}) 404 { 405 _M_variant._M_iterator._M_type 406 = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>); 407 } 408 409 private: 410 _Iterator_state _S_reverse_state_Parameter411 _S_reverse_state(_Iterator_state __state) 412 { 413 switch (__state) 414 { 415 case __begin: 416 return __rend; 417 case __middle: 418 return __rmiddle; 419 case __end: 420 return __rbegin; 421 default: 422 return __state; 423 } 424 } 425 426 public: 427 #endif 428 429 template<typename _Sequence> _Parameter_Parameter430 _Parameter(const _Safe_sequence<_Sequence>& __seq, 431 const char* __name, _Is_sequence) 432 : _M_kind(__sequence), _M_variant() 433 { 434 _M_variant._M_sequence._M_name = __name; 435 _M_variant._M_sequence._M_address = 436 static_cast<const _Sequence*>(std::__addressof(__seq)); 437 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 438 } 439 440 template<typename _Sequence> _Parameter_Parameter441 _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 442 : _M_kind(__sequence), _M_variant() 443 { 444 _M_variant._M_sequence._M_name = __name; 445 _M_variant._M_sequence._M_address = std::__addressof(__seq); 446 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 447 } 448 449 template<typename _Iterator> _Parameter_Parameter450 _Parameter(const _Iterator& __it, const char* __name, 451 _Is_iterator_value_type) 452 : _M_kind(__iterator_value_type), _M_variant() 453 { 454 _M_variant._M_iterator_value_type._M_name = __name; 455 _M_variant._M_iterator_value_type._M_type = 456 _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); 457 } 458 459 template<typename _Type> _Parameter_Parameter460 _Parameter(const _Type& __inst, const char* __name, _Is_instance) 461 : _M_kind(__instance), _M_variant() 462 { 463 _M_variant._M_instance._M_name = __name; 464 _M_variant._M_instance._M_address = &__inst; 465 _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); 466 } 467 468 #if !_GLIBCXX_INLINE_VERSION 469 void 470 _M_print_field(const _Error_formatter* __formatter, 471 const char* __name) const _GLIBCXX_DEPRECATED; 472 473 void 474 _M_print_description(const _Error_formatter* __formatter) 475 const _GLIBCXX_DEPRECATED; 476 #endif 477 }; 478 479 template<typename _Iterator> 480 _Error_formatter& 481 _M_iterator(const _Iterator& __it, const char* __name = 0) 482 { 483 if (_M_num_parameters < std::size_t(__max_parameters)) 484 _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 485 _Is_iterator()); 486 return *this; 487 } 488 489 template<typename _Iterator> 490 _Error_formatter& 491 _M_iterator_value_type(const _Iterator& __it, 492 const char* __name = 0) 493 { 494 if (_M_num_parameters < __max_parameters) 495 _M_parameters[_M_num_parameters++] = 496 _Parameter(__it, __name, _Is_iterator_value_type()); 497 return *this; 498 } 499 500 _Error_formatter& 501 _M_integer(long __value, const char* __name = 0) 502 { 503 if (_M_num_parameters < __max_parameters) 504 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 505 return *this; 506 } 507 508 _Error_formatter& 509 _M_string(const char* __value, const char* __name = 0) 510 { 511 if (_M_num_parameters < __max_parameters) 512 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 513 return *this; 514 } 515 516 template<typename _Sequence> 517 _Error_formatter& 518 _M_sequence(const _Sequence& __seq, const char* __name = 0) 519 { 520 if (_M_num_parameters < __max_parameters) 521 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 522 _Is_sequence()); 523 return *this; 524 } 525 526 template<typename _Type> 527 _Error_formatter& 528 _M_instance(const _Type& __inst, const char* __name = 0) 529 { 530 if (_M_num_parameters < __max_parameters) 531 _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, 532 _Is_instance()); 533 return *this; 534 } 535 536 _Error_formatter& _M_message(const char * __text)537 _M_message(const char* __text) 538 { _M_text = __text; return *this; } 539 540 // Kept const qualifier for backward compatibility, to keep the same 541 // exported symbol. 542 _Error_formatter& 543 _M_message(_Debug_msg_id __id) const throw (); 544 545 _GLIBCXX_NORETURN void 546 _M_error() const; 547 548 #if !_GLIBCXX_INLINE_VERSION 549 template<typename _Tp> 550 void 551 _M_format_word(char*, int, const char*, _Tp) 552 const throw () _GLIBCXX_DEPRECATED; 553 554 void 555 _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; 556 557 void 558 _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; 559 #endif 560 561 private: _Error_formatter(const char * __file,unsigned int __line,const char * __function)562 _Error_formatter(const char* __file, unsigned int __line, 563 const char* __function) 564 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) 565 , _M_function(__function) 566 { } 567 568 #if !_GLIBCXX_INLINE_VERSION 569 void 570 _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; 571 #endif 572 573 enum { __max_parameters = 9 }; 574 575 const char* _M_file; 576 unsigned int _M_line; 577 _Parameter _M_parameters[__max_parameters]; 578 unsigned int _M_num_parameters; 579 const char* _M_text; 580 const char* _M_function; 581 582 public: 583 static _Error_formatter& _S_at(const char * __file,unsigned int __line,const char * __function)584 _S_at(const char* __file, unsigned int __line, const char* __function) 585 { 586 static _Error_formatter __formatter(__file, __line, __function); 587 return __formatter; 588 } 589 }; 590 } // namespace __gnu_debug 591 592 #undef _GLIBCXX_TYPEID 593 594 #endif 595