1// Debug-mode error formatting implementation -*- C++ -*- 2 3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 3, 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// Under Section 7 of GPL version 3, you are granted additional 18// permissions described in the GCC Runtime Library Exception, version 19// 3.1, as published by the Free Software Foundation. 20 21// You should have received a copy of the GNU General Public License and 22// a copy of the GCC Runtime Library Exception along with this program; 23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24// <http://www.gnu.org/licenses/>. 25 26/** @file debug/formatter.h 27 * This file is a GNU debug extension to the Standard C++ Library. 28 */ 29 30#ifndef _GLIBCXX_DEBUG_FORMATTER_H 31#define _GLIBCXX_DEBUG_FORMATTER_H 1 32 33#include <bits/c++config.h> 34#include <bits/cpp_type_traits.h> 35#include <typeinfo> 36 37namespace __gnu_debug 38{ 39 using std::type_info; 40 41 template<typename _Iterator> 42 bool __check_singular(_Iterator&); 43 44 class _Safe_sequence_base; 45 46 template<typename _Iterator, typename _Sequence> 47 class _Safe_iterator; 48 49 template<typename _Sequence> 50 class _Safe_sequence; 51 52 enum _Debug_msg_id 53 { 54 // General checks 55 __msg_valid_range, 56 __msg_insert_singular, 57 __msg_insert_different, 58 __msg_erase_bad, 59 __msg_erase_different, 60 __msg_subscript_oob, 61 __msg_empty, 62 __msg_unpartitioned, 63 __msg_unpartitioned_pred, 64 __msg_unsorted, 65 __msg_unsorted_pred, 66 __msg_not_heap, 67 __msg_not_heap_pred, 68 // std::bitset checks 69 __msg_bad_bitset_write, 70 __msg_bad_bitset_read, 71 __msg_bad_bitset_flip, 72 // std::list checks 73 __msg_self_splice, 74 __msg_splice_alloc, 75 __msg_splice_bad, 76 __msg_splice_other, 77 __msg_splice_overlap, 78 // iterator checks 79 __msg_init_singular, 80 __msg_init_copy_singular, 81 __msg_init_const_singular, 82 __msg_copy_singular, 83 __msg_bad_deref, 84 __msg_bad_inc, 85 __msg_bad_dec, 86 __msg_iter_subscript_oob, 87 __msg_advance_oob, 88 __msg_retreat_oob, 89 __msg_iter_compare_bad, 90 __msg_compare_different, 91 __msg_iter_order_bad, 92 __msg_order_different, 93 __msg_distance_bad, 94 __msg_distance_different, 95 // istream_iterator 96 __msg_deref_istream, 97 __msg_inc_istream, 98 // ostream_iterator 99 __msg_output_ostream, 100 // istreambuf_iterator 101 __msg_deref_istreambuf, 102 __msg_inc_istreambuf, 103 // forward_list 104 __msg_insert_after_end, 105 __msg_erase_after_bad, 106 __msg_valid_range2 107 }; 108 109 class _Error_formatter 110 { 111 /// Whether an iterator is constant, mutable, or unknown 112 enum _Constness 113 { 114 __unknown_constness, 115 __const_iterator, 116 __mutable_iterator, 117 __last_constness 118 }; 119 120 // The state of the iterator (fine-grained), if we know it. 121 enum _Iterator_state 122 { 123 __unknown_state, 124 __singular, // singular, may still be attached to a sequence 125 __begin, // dereferenceable, and at the beginning 126 __middle, // dereferenceable, not at the beginning 127 __end, // past-the-end, may be at beginning if sequence empty 128 __before_begin, // before begin 129 __last_state 130 }; 131 132 // Tags denoting the type of parameter for construction 133 struct _Is_iterator { }; 134 struct _Is_sequence { }; 135 136 // A parameter that may be referenced by an error message 137 struct _Parameter 138 { 139 enum 140 { 141 __unused_param, 142 __iterator, 143 __sequence, 144 __integer, 145 __string 146 } _M_kind; 147 148 union 149 { 150 // When _M_kind == __iterator 151 struct 152 { 153 const char* _M_name; 154 const void* _M_address; 155 const type_info* _M_type; 156 _Constness _M_constness; 157 _Iterator_state _M_state; 158 const void* _M_sequence; 159 const type_info* _M_seq_type; 160 } _M_iterator; 161 162 // When _M_kind == __sequence 163 struct 164 { 165 const char* _M_name; 166 const void* _M_address; 167 const type_info* _M_type; 168 } _M_sequence; 169 170 // When _M_kind == __integer 171 struct 172 { 173 const char* _M_name; 174 long _M_value; 175 } _M_integer; 176 177 // When _M_kind == __string 178 struct 179 { 180 const char* _M_name; 181 const char* _M_value; 182 } _M_string; 183 } _M_variant; 184 185 _Parameter() : _M_kind(__unused_param), _M_variant() { } 186 187 _Parameter(long __value, const char* __name) 188 : _M_kind(__integer), _M_variant() 189 { 190 _M_variant._M_integer._M_name = __name; 191 _M_variant._M_integer._M_value = __value; 192 } 193 194 _Parameter(const char* __value, const char* __name) 195 : _M_kind(__string), _M_variant() 196 { 197 _M_variant._M_string._M_name = __name; 198 _M_variant._M_string._M_value = __value; 199 } 200 201 template<typename _Iterator, typename _Sequence> 202 _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it, 203 const char* __name, _Is_iterator) 204 : _M_kind(__iterator), _M_variant() 205 { 206 _M_variant._M_iterator._M_name = __name; 207 _M_variant._M_iterator._M_address = &__it; 208#ifdef __GXX_RTTI 209 _M_variant._M_iterator._M_type = &typeid(__it); 210#else 211 _M_variant._M_iterator._M_type = 0; 212#endif 213 _M_variant._M_iterator._M_constness = 214 std::__are_same<_Safe_iterator<_Iterator, _Sequence>, 215 typename _Sequence::iterator>:: 216 __value ? __mutable_iterator : __const_iterator; 217 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 218#ifdef __GXX_RTTI 219 _M_variant._M_iterator._M_seq_type = &typeid(_Sequence); 220#else 221 _M_variant._M_iterator._M_seq_type = 0; 222#endif 223 224 if (__it._M_singular()) 225 _M_variant._M_iterator._M_state = __singular; 226 else 227 { 228 if (__it._M_is_before_begin()) 229 _M_variant._M_iterator._M_state = __before_begin; 230 else if (__it._M_is_end()) 231 _M_variant._M_iterator._M_state = __end; 232 else if (__it._M_is_begin()) 233 _M_variant._M_iterator._M_state = __begin; 234 else 235 _M_variant._M_iterator._M_state = __middle; 236 } 237 } 238 239 template<typename _Type> 240 _Parameter(const _Type*& __it, const char* __name, _Is_iterator) 241 : _M_kind(__iterator), _M_variant() 242 { 243 _M_variant._M_iterator._M_name = __name; 244 _M_variant._M_iterator._M_address = &__it; 245#ifdef __GXX_RTTI 246 _M_variant._M_iterator._M_type = &typeid(__it); 247#else 248 _M_variant._M_iterator._M_type = 0; 249#endif 250 _M_variant._M_iterator._M_constness = __mutable_iterator; 251 _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 252 _M_variant._M_iterator._M_sequence = 0; 253 _M_variant._M_iterator._M_seq_type = 0; 254 } 255 256 template<typename _Type> 257 _Parameter(_Type*& __it, const char* __name, _Is_iterator) 258 : _M_kind(__iterator), _M_variant() 259 { 260 _M_variant._M_iterator._M_name = __name; 261 _M_variant._M_iterator._M_address = &__it; 262#ifdef __GXX_RTTI 263 _M_variant._M_iterator._M_type = &typeid(__it); 264#else 265 _M_variant._M_iterator._M_type = 0; 266#endif 267 _M_variant._M_iterator._M_constness = __const_iterator; 268 _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 269 _M_variant._M_iterator._M_sequence = 0; 270 _M_variant._M_iterator._M_seq_type = 0; 271 } 272 273 template<typename _Iterator> 274 _Parameter(const _Iterator& __it, const char* __name, _Is_iterator) 275 : _M_kind(__iterator), _M_variant() 276 { 277 _M_variant._M_iterator._M_name = __name; 278 _M_variant._M_iterator._M_address = &__it; 279#ifdef __GXX_RTTI 280 _M_variant._M_iterator._M_type = &typeid(__it); 281#else 282 _M_variant._M_iterator._M_type = 0; 283#endif 284 _M_variant._M_iterator._M_constness = __unknown_constness; 285 _M_variant._M_iterator._M_state = 286 __gnu_debug::__check_singular(__it)? __singular : __unknown_state; 287 _M_variant._M_iterator._M_sequence = 0; 288 _M_variant._M_iterator._M_seq_type = 0; 289 } 290 291 template<typename _Sequence> 292 _Parameter(const _Safe_sequence<_Sequence>& __seq, 293 const char* __name, _Is_sequence) 294 : _M_kind(__sequence), _M_variant() 295 { 296 _M_variant._M_sequence._M_name = __name; 297 _M_variant._M_sequence._M_address = 298 static_cast<const _Sequence*>(&__seq); 299#ifdef __GXX_RTTI 300 _M_variant._M_sequence._M_type = &typeid(_Sequence); 301#else 302 _M_variant._M_sequence._M_type = 0; 303#endif 304 } 305 306 template<typename _Sequence> 307 _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 308 : _M_kind(__sequence), _M_variant() 309 { 310 _M_variant._M_sequence._M_name = __name; 311 _M_variant._M_sequence._M_address = &__seq; 312#ifdef __GXX_RTTI 313 _M_variant._M_sequence._M_type = &typeid(_Sequence); 314#else 315 _M_variant._M_sequence._M_type = 0; 316#endif 317 } 318 319 void 320 _M_print_field(const _Error_formatter* __formatter, 321 const char* __name) const; 322 323 void 324 _M_print_description(const _Error_formatter* __formatter) const; 325 }; 326 327 friend struct _Parameter; 328 329 public: 330 template<typename _Iterator> 331 const _Error_formatter& 332 _M_iterator(const _Iterator& __it, const char* __name = 0) const 333 { 334 if (_M_num_parameters < std::size_t(__max_parameters)) 335 _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 336 _Is_iterator()); 337 return *this; 338 } 339 340 const _Error_formatter& 341 _M_integer(long __value, const char* __name = 0) const 342 { 343 if (_M_num_parameters < std::size_t(__max_parameters)) 344 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 345 return *this; 346 } 347 348 const _Error_formatter& 349 _M_string(const char* __value, const char* __name = 0) const 350 { 351 if (_M_num_parameters < std::size_t(__max_parameters)) 352 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 353 return *this; 354 } 355 356 template<typename _Sequence> 357 const _Error_formatter& 358 _M_sequence(const _Sequence& __seq, const char* __name = 0) const 359 { 360 if (_M_num_parameters < std::size_t(__max_parameters)) 361 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 362 _Is_sequence()); 363 return *this; 364 } 365 366 const _Error_formatter& 367 _M_message(const char* __text) const 368 { _M_text = __text; return *this; } 369 370 const _Error_formatter& 371 _M_message(_Debug_msg_id __id) const throw (); 372 373 _GLIBCXX_NORETURN void 374 _M_error() const; 375 376 private: 377 _Error_formatter(const char* __file, std::size_t __line) 378 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0), 379 _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 380 { _M_get_max_length(); } 381 382 template<typename _Tp> 383 void 384 _M_format_word(char*, int, const char*, _Tp) const throw (); 385 386 void 387 _M_print_word(const char* __word) const; 388 389 void 390 _M_print_string(const char* __string) const; 391 392 void 393 _M_get_max_length() const throw (); 394 395 enum { __max_parameters = 9 }; 396 397 const char* _M_file; 398 std::size_t _M_line; 399 mutable _Parameter _M_parameters[__max_parameters]; 400 mutable std::size_t _M_num_parameters; 401 mutable const char* _M_text; 402 mutable std::size_t _M_max_length; 403 enum { _M_indent = 4 } ; 404 mutable std::size_t _M_column; 405 mutable bool _M_first_line; 406 mutable bool _M_wordwrap; 407 408 public: 409 static _Error_formatter 410 _M_at(const char* __file, std::size_t __line) 411 { return _Error_formatter(__file, __line); } 412 }; 413} // namespace __gnu_debug 414 415#endif 416