1 // Debug-mode error formatting implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2016 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 #include <bits/cpp_type_traits.h> 34 35 #if __cpp_rtti 36 # include <typeinfo> 37 # define _GLIBCXX_TYPEID(_Type) &typeid(_Type) 38 #else 39 namespace std 40 { 41 class type_info; 42 } 43 # define _GLIBCXX_TYPEID(_Type) 0 44 #endif 45 46 namespace __gnu_debug 47 { 48 using std::type_info; 49 50 template<typename _Iterator> 51 bool __check_singular(const _Iterator&); 52 53 class _Safe_sequence_base; 54 55 template<typename _Iterator, typename _Sequence> 56 class _Safe_iterator; 57 58 template<typename _Iterator, typename _Sequence> 59 class _Safe_local_iterator; 60 61 template<typename _Sequence> 62 class _Safe_sequence; 63 64 enum _Debug_msg_id 65 { 66 // General checks 67 __msg_valid_range, 68 __msg_insert_singular, 69 __msg_insert_different, 70 __msg_erase_bad, 71 __msg_erase_different, 72 __msg_subscript_oob, 73 __msg_empty, 74 __msg_unpartitioned, 75 __msg_unpartitioned_pred, 76 __msg_unsorted, 77 __msg_unsorted_pred, 78 __msg_not_heap, 79 __msg_not_heap_pred, 80 // std::bitset checks 81 __msg_bad_bitset_write, 82 __msg_bad_bitset_read, 83 __msg_bad_bitset_flip, 84 // std::list checks 85 __msg_self_splice, 86 __msg_splice_alloc, 87 __msg_splice_bad, 88 __msg_splice_other, 89 __msg_splice_overlap, 90 // iterator checks 91 __msg_init_singular, 92 __msg_init_copy_singular, 93 __msg_init_const_singular, 94 __msg_copy_singular, 95 __msg_bad_deref, 96 __msg_bad_inc, 97 __msg_bad_dec, 98 __msg_iter_subscript_oob, 99 __msg_advance_oob, 100 __msg_retreat_oob, 101 __msg_iter_compare_bad, 102 __msg_compare_different, 103 __msg_iter_order_bad, 104 __msg_order_different, 105 __msg_distance_bad, 106 __msg_distance_different, 107 // istream_iterator 108 __msg_deref_istream, 109 __msg_inc_istream, 110 // ostream_iterator 111 __msg_output_ostream, 112 // istreambuf_iterator 113 __msg_deref_istreambuf, 114 __msg_inc_istreambuf, 115 // forward_list 116 __msg_insert_after_end, 117 __msg_erase_after_bad, 118 __msg_valid_range2, 119 // unordered container local iterators 120 __msg_local_iter_compare_bad, 121 __msg_non_empty_range, 122 // self move assign 123 __msg_self_move_assign, 124 // unordered container buckets 125 __msg_bucket_index_oob, 126 __msg_valid_load_factor, 127 // others 128 __msg_equal_allocs, 129 __msg_insert_range_from_self, 130 __msg_irreflexive_ordering 131 }; 132 133 class _Error_formatter 134 { 135 // Tags denoting the type of parameter for construction 136 struct _Is_iterator { }; 137 struct _Is_iterator_value_type { }; 138 struct _Is_sequence { }; 139 struct _Is_instance { }; 140 141 public: 142 /// Whether an iterator is constant, mutable, or unknown 143 enum _Constness 144 { 145 __unknown_constness, 146 __const_iterator, 147 __mutable_iterator, 148 __last_constness 149 }; 150 151 // The state of the iterator (fine-grained), if we know it. 152 enum _Iterator_state 153 { 154 __unknown_state, 155 __singular, // singular, may still be attached to a sequence 156 __begin, // dereferenceable, and at the beginning 157 __middle, // dereferenceable, not at the beginning 158 __end, // past-the-end, may be at beginning if sequence empty 159 __before_begin, // before begin 160 __last_state 161 }; 162 163 // A parameter that may be referenced by an error message 164 struct _Parameter 165 { 166 enum 167 { 168 __unused_param, 169 __iterator, 170 __sequence, 171 __integer, 172 __string, 173 __instance, 174 __iterator_value_type 175 } _M_kind; 176 177 struct _Type 178 { 179 const char* _M_name; 180 const type_info* _M_type; 181 }; 182 183 struct _Instance : _Type 184 { 185 const void* _M_address; 186 }; 187 188 union 189 { 190 // When _M_kind == __iterator 191 struct : _Instance 192 { 193 _Constness _M_constness; 194 _Iterator_state _M_state; 195 const void* _M_sequence; 196 const type_info* _M_seq_type; 197 } _M_iterator; 198 199 // When _M_kind == __sequence 200 _Instance _M_sequence; 201 202 // When _M_kind == __integer 203 struct 204 { 205 const char* _M_name; 206 long _M_value; 207 } _M_integer; 208 209 // When _M_kind == __string 210 struct 211 { 212 const char* _M_name; 213 const char* _M_value; 214 } _M_string; 215 216 // When _M_kind == __instance 217 _Instance _M_instance; 218 219 // When _M_kind == __iterator_value_type 220 _Type _M_iterator_value_type; 221 } _M_variant; 222 _Parameter_Parameter223 _Parameter() : _M_kind(__unused_param), _M_variant() { } 224 _Parameter_Parameter225 _Parameter(long __value, const char* __name) 226 : _M_kind(__integer), _M_variant() 227 { 228 _M_variant._M_integer._M_name = __name; 229 _M_variant._M_integer._M_value = __value; 230 } 231 _Parameter_Parameter232 _Parameter(const char* __value, const char* __name) 233 : _M_kind(__string), _M_variant() 234 { 235 _M_variant._M_string._M_name = __name; 236 _M_variant._M_string._M_value = __value; 237 } 238 239 template<typename _Iterator, typename _Sequence> _Parameter_Parameter240 _Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it, 241 const char* __name, _Is_iterator) 242 : _M_kind(__iterator), _M_variant() 243 { 244 _M_variant._M_iterator._M_name = __name; 245 _M_variant._M_iterator._M_address = std::__addressof(__it); 246 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 247 _M_variant._M_iterator._M_constness = 248 std::__are_same<_Safe_iterator<_Iterator, _Sequence>, 249 typename _Sequence::iterator>:: 250 __value ? __mutable_iterator : __const_iterator; 251 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 252 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 253 254 if (__it._M_singular()) 255 _M_variant._M_iterator._M_state = __singular; 256 else 257 { 258 if (__it._M_is_before_begin()) 259 _M_variant._M_iterator._M_state = __before_begin; 260 else if (__it._M_is_end()) 261 _M_variant._M_iterator._M_state = __end; 262 else if (__it._M_is_begin()) 263 _M_variant._M_iterator._M_state = __begin; 264 else 265 _M_variant._M_iterator._M_state = __middle; 266 } 267 } 268 269 template<typename _Iterator, typename _Sequence> _Parameter_Parameter270 _Parameter(_Safe_local_iterator<_Iterator, _Sequence> 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(__it); 277 _M_variant._M_iterator._M_constness = 278 std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>, 279 typename _Sequence::local_iterator>:: 280 __value ? __mutable_iterator : __const_iterator; 281 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 282 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 283 284 if (__it._M_singular()) 285 _M_variant._M_iterator._M_state = __singular; 286 else 287 { 288 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 _Type> _Parameter_Parameter298 _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) 299 : _M_kind(__iterator), _M_variant() 300 { 301 _M_variant._M_iterator._M_name = __name; 302 _M_variant._M_iterator._M_address = std::__addressof(__it); 303 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 304 _M_variant._M_iterator._M_constness = __const_iterator; 305 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 306 _M_variant._M_iterator._M_sequence = 0; 307 _M_variant._M_iterator._M_seq_type = 0; 308 } 309 310 template<typename _Type> _Parameter_Parameter311 _Parameter(_Type* const& __it, const char* __name, _Is_iterator) 312 : _M_kind(__iterator), _M_variant() 313 { 314 _M_variant._M_iterator._M_name = __name; 315 _M_variant._M_iterator._M_address = std::__addressof(__it); 316 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 317 _M_variant._M_iterator._M_constness = __mutable_iterator; 318 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 319 _M_variant._M_iterator._M_sequence = 0; 320 _M_variant._M_iterator._M_seq_type = 0; 321 } 322 323 template<typename _Iterator> _Parameter_Parameter324 _Parameter(_Iterator 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 = __unknown_constness; 331 _M_variant._M_iterator._M_state = 332 __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; 333 _M_variant._M_iterator._M_sequence = 0; 334 _M_variant._M_iterator._M_seq_type = 0; 335 } 336 337 template<typename _Sequence> _Parameter_Parameter338 _Parameter(const _Safe_sequence<_Sequence>& __seq, 339 const char* __name, _Is_sequence) 340 : _M_kind(__sequence), _M_variant() 341 { 342 _M_variant._M_sequence._M_name = __name; 343 _M_variant._M_sequence._M_address = 344 static_cast<const _Sequence*>(std::__addressof(__seq)); 345 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 346 } 347 348 template<typename _Sequence> _Parameter_Parameter349 _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 350 : _M_kind(__sequence), _M_variant() 351 { 352 _M_variant._M_sequence._M_name = __name; 353 _M_variant._M_sequence._M_address = std::__addressof(__seq); 354 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 355 } 356 357 template<typename _Iterator> _Parameter_Parameter358 _Parameter(const _Iterator& __it, const char* __name, 359 _Is_iterator_value_type) 360 : _M_kind(__iterator_value_type), _M_variant() 361 { 362 _M_variant._M_iterator_value_type._M_name = __name; 363 _M_variant._M_iterator_value_type._M_type = 364 _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); 365 } 366 367 template<typename _Type> _Parameter_Parameter368 _Parameter(const _Type& __inst, const char* __name, _Is_instance) 369 : _M_kind(__instance), _M_variant() 370 { 371 _M_variant._M_instance._M_name = __name; 372 _M_variant._M_instance._M_address = &__inst; 373 _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); 374 } 375 376 void 377 _M_print_field(const _Error_formatter* __formatter, 378 const char* __name) const _GLIBCXX_DEPRECATED; 379 380 void 381 _M_print_description(const _Error_formatter* __formatter) 382 const _GLIBCXX_DEPRECATED; 383 }; 384 385 template<typename _Iterator> 386 _Error_formatter& 387 _M_iterator(const _Iterator& __it, const char* __name = 0) 388 { 389 if (_M_num_parameters < std::size_t(__max_parameters)) 390 _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 391 _Is_iterator()); 392 return *this; 393 } 394 395 template<typename _Iterator> 396 _Error_formatter& 397 _M_iterator_value_type(const _Iterator& __it, 398 const char* __name = 0) 399 { 400 if (_M_num_parameters < __max_parameters) 401 _M_parameters[_M_num_parameters++] = 402 _Parameter(__it, __name, _Is_iterator_value_type()); 403 return *this; 404 } 405 406 _Error_formatter& 407 _M_integer(long __value, const char* __name = 0) 408 { 409 if (_M_num_parameters < __max_parameters) 410 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 411 return *this; 412 } 413 414 _Error_formatter& 415 _M_string(const char* __value, const char* __name = 0) 416 { 417 if (_M_num_parameters < __max_parameters) 418 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 419 return *this; 420 } 421 422 template<typename _Sequence> 423 _Error_formatter& 424 _M_sequence(const _Sequence& __seq, const char* __name = 0) 425 { 426 if (_M_num_parameters < __max_parameters) 427 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 428 _Is_sequence()); 429 return *this; 430 } 431 432 template<typename _Type> 433 _Error_formatter& 434 _M_instance(const _Type& __inst, const char* __name = 0) 435 { 436 if (_M_num_parameters < __max_parameters) 437 _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, 438 _Is_instance()); 439 return *this; 440 } 441 442 _Error_formatter& _M_message(const char * __text)443 _M_message(const char* __text) 444 { _M_text = __text; return *this; } 445 446 // Kept const qualifier for backward compatibility, to keep the same 447 // exported symbol. 448 _Error_formatter& 449 _M_message(_Debug_msg_id __id) const throw (); 450 451 _GLIBCXX_NORETURN void 452 _M_error() const; 453 454 template<typename _Tp> 455 void 456 _M_format_word(char*, int, const char*, _Tp) 457 const throw () _GLIBCXX_DEPRECATED; 458 459 void 460 _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; 461 462 void 463 _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; 464 465 private: _Error_formatter(const char * __file,unsigned int __line)466 _Error_formatter(const char* __file, unsigned int __line) 467 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) 468 { } 469 470 void 471 _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; 472 473 enum { __max_parameters = 9 }; 474 475 const char* _M_file; 476 unsigned int _M_line; 477 _Parameter _M_parameters[__max_parameters]; 478 unsigned int _M_num_parameters; 479 const char* _M_text; 480 481 public: 482 static _Error_formatter& _M_at(const char * __file,unsigned int __line)483 _M_at(const char* __file, unsigned int __line) 484 { 485 static _Error_formatter __formatter(__file, __line); 486 return __formatter; 487 } 488 }; 489 } // namespace __gnu_debug 490 491 #undef _GLIBCXX_TYPEID 492 493 #endif 494