libstdc++
|
00001 // Debug-mode error formatting implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003-2018 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file debug/formatter.h 00026 * This file is a GNU debug extension to the Standard C++ Library. 00027 */ 00028 00029 #ifndef _GLIBCXX_DEBUG_FORMATTER_H 00030 #define _GLIBCXX_DEBUG_FORMATTER_H 1 00031 00032 #include <bits/c++config.h> 00033 #include <bits/cpp_type_traits.h> 00034 00035 #if __cpp_rtti 00036 # include <typeinfo> 00037 # define _GLIBCXX_TYPEID(_Type) &typeid(_Type) 00038 #else 00039 namespace std 00040 { 00041 class type_info; 00042 } 00043 # define _GLIBCXX_TYPEID(_Type) 0 00044 #endif 00045 00046 namespace __gnu_debug 00047 { 00048 using std::type_info; 00049 00050 template<typename _Iterator> 00051 bool __check_singular(const _Iterator&); 00052 00053 class _Safe_sequence_base; 00054 00055 template<typename _Iterator, typename _Sequence> 00056 class _Safe_iterator; 00057 00058 template<typename _Iterator, typename _Sequence> 00059 class _Safe_local_iterator; 00060 00061 template<typename _Sequence> 00062 class _Safe_sequence; 00063 00064 enum _Debug_msg_id 00065 { 00066 // General checks 00067 __msg_valid_range, 00068 __msg_insert_singular, 00069 __msg_insert_different, 00070 __msg_erase_bad, 00071 __msg_erase_different, 00072 __msg_subscript_oob, 00073 __msg_empty, 00074 __msg_unpartitioned, 00075 __msg_unpartitioned_pred, 00076 __msg_unsorted, 00077 __msg_unsorted_pred, 00078 __msg_not_heap, 00079 __msg_not_heap_pred, 00080 // std::bitset checks 00081 __msg_bad_bitset_write, 00082 __msg_bad_bitset_read, 00083 __msg_bad_bitset_flip, 00084 // std::list checks 00085 __msg_self_splice, 00086 __msg_splice_alloc, 00087 __msg_splice_bad, 00088 __msg_splice_other, 00089 __msg_splice_overlap, 00090 // iterator checks 00091 __msg_init_singular, 00092 __msg_init_copy_singular, 00093 __msg_init_const_singular, 00094 __msg_copy_singular, 00095 __msg_bad_deref, 00096 __msg_bad_inc, 00097 __msg_bad_dec, 00098 __msg_iter_subscript_oob, 00099 __msg_advance_oob, 00100 __msg_retreat_oob, 00101 __msg_iter_compare_bad, 00102 __msg_compare_different, 00103 __msg_iter_order_bad, 00104 __msg_order_different, 00105 __msg_distance_bad, 00106 __msg_distance_different, 00107 // istream_iterator 00108 __msg_deref_istream, 00109 __msg_inc_istream, 00110 // ostream_iterator 00111 __msg_output_ostream, 00112 // istreambuf_iterator 00113 __msg_deref_istreambuf, 00114 __msg_inc_istreambuf, 00115 // forward_list 00116 __msg_insert_after_end, 00117 __msg_erase_after_bad, 00118 __msg_valid_range2, 00119 // unordered container local iterators 00120 __msg_local_iter_compare_bad, 00121 __msg_non_empty_range, 00122 // self move assign 00123 __msg_self_move_assign, 00124 // unordered container buckets 00125 __msg_bucket_index_oob, 00126 __msg_valid_load_factor, 00127 // others 00128 __msg_equal_allocs, 00129 __msg_insert_range_from_self, 00130 __msg_irreflexive_ordering 00131 }; 00132 00133 class _Error_formatter 00134 { 00135 // Tags denoting the type of parameter for construction 00136 struct _Is_iterator { }; 00137 struct _Is_iterator_value_type { }; 00138 struct _Is_sequence { }; 00139 struct _Is_instance { }; 00140 00141 public: 00142 /// Whether an iterator is constant, mutable, or unknown 00143 enum _Constness 00144 { 00145 __unknown_constness, 00146 __const_iterator, 00147 __mutable_iterator, 00148 __last_constness 00149 }; 00150 00151 // The state of the iterator (fine-grained), if we know it. 00152 enum _Iterator_state 00153 { 00154 __unknown_state, 00155 __singular, // singular, may still be attached to a sequence 00156 __begin, // dereferenceable, and at the beginning 00157 __middle, // dereferenceable, not at the beginning 00158 __end, // past-the-end, may be at beginning if sequence empty 00159 __before_begin, // before begin 00160 __last_state 00161 }; 00162 00163 // A parameter that may be referenced by an error message 00164 struct _Parameter 00165 { 00166 enum 00167 { 00168 __unused_param, 00169 __iterator, 00170 __sequence, 00171 __integer, 00172 __string, 00173 __instance, 00174 __iterator_value_type 00175 } _M_kind; 00176 00177 struct _Type 00178 { 00179 const char* _M_name; 00180 const type_info* _M_type; 00181 }; 00182 00183 struct _Instance : _Type 00184 { 00185 const void* _M_address; 00186 }; 00187 00188 union 00189 { 00190 // When _M_kind == __iterator 00191 struct : _Instance 00192 { 00193 _Constness _M_constness; 00194 _Iterator_state _M_state; 00195 const void* _M_sequence; 00196 const type_info* _M_seq_type; 00197 } _M_iterator; 00198 00199 // When _M_kind == __sequence 00200 _Instance _M_sequence; 00201 00202 // When _M_kind == __integer 00203 struct 00204 { 00205 const char* _M_name; 00206 long _M_value; 00207 } _M_integer; 00208 00209 // When _M_kind == __string 00210 struct 00211 { 00212 const char* _M_name; 00213 const char* _M_value; 00214 } _M_string; 00215 00216 // When _M_kind == __instance 00217 _Instance _M_instance; 00218 00219 // When _M_kind == __iterator_value_type 00220 _Type _M_iterator_value_type; 00221 } _M_variant; 00222 00223 _Parameter() : _M_kind(__unused_param), _M_variant() { } 00224 00225 _Parameter(long __value, const char* __name) 00226 : _M_kind(__integer), _M_variant() 00227 { 00228 _M_variant._M_integer._M_name = __name; 00229 _M_variant._M_integer._M_value = __value; 00230 } 00231 00232 _Parameter(const char* __value, const char* __name) 00233 : _M_kind(__string), _M_variant() 00234 { 00235 _M_variant._M_string._M_name = __name; 00236 _M_variant._M_string._M_value = __value; 00237 } 00238 00239 template<typename _Iterator, typename _Sequence> 00240 _Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it, 00241 const char* __name, _Is_iterator) 00242 : _M_kind(__iterator), _M_variant() 00243 { 00244 _M_variant._M_iterator._M_name = __name; 00245 _M_variant._M_iterator._M_address = std::__addressof(__it); 00246 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 00247 _M_variant._M_iterator._M_constness = 00248 std::__are_same<_Safe_iterator<_Iterator, _Sequence>, 00249 typename _Sequence::iterator>:: 00250 __value ? __mutable_iterator : __const_iterator; 00251 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 00252 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 00253 00254 if (__it._M_singular()) 00255 _M_variant._M_iterator._M_state = __singular; 00256 else 00257 { 00258 if (__it._M_is_before_begin()) 00259 _M_variant._M_iterator._M_state = __before_begin; 00260 else if (__it._M_is_end()) 00261 _M_variant._M_iterator._M_state = __end; 00262 else if (__it._M_is_begin()) 00263 _M_variant._M_iterator._M_state = __begin; 00264 else 00265 _M_variant._M_iterator._M_state = __middle; 00266 } 00267 } 00268 00269 template<typename _Iterator, typename _Sequence> 00270 _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, 00271 const char* __name, _Is_iterator) 00272 : _M_kind(__iterator), _M_variant() 00273 { 00274 _M_variant._M_iterator._M_name = __name; 00275 _M_variant._M_iterator._M_address = std::__addressof(__it); 00276 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 00277 _M_variant._M_iterator._M_constness = 00278 std::__are_same<_Safe_local_iterator<_Iterator, _Sequence>, 00279 typename _Sequence::local_iterator>:: 00280 __value ? __mutable_iterator : __const_iterator; 00281 _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 00282 _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); 00283 00284 if (__it._M_singular()) 00285 _M_variant._M_iterator._M_state = __singular; 00286 else 00287 { 00288 if (__it._M_is_end()) 00289 _M_variant._M_iterator._M_state = __end; 00290 else if (__it._M_is_begin()) 00291 _M_variant._M_iterator._M_state = __begin; 00292 else 00293 _M_variant._M_iterator._M_state = __middle; 00294 } 00295 } 00296 00297 template<typename _Type> 00298 _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) 00299 : _M_kind(__iterator), _M_variant() 00300 { 00301 _M_variant._M_iterator._M_name = __name; 00302 _M_variant._M_iterator._M_address = std::__addressof(__it); 00303 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 00304 _M_variant._M_iterator._M_constness = __const_iterator; 00305 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 00306 _M_variant._M_iterator._M_sequence = 0; 00307 _M_variant._M_iterator._M_seq_type = 0; 00308 } 00309 00310 template<typename _Type> 00311 _Parameter(_Type* const& __it, const char* __name, _Is_iterator) 00312 : _M_kind(__iterator), _M_variant() 00313 { 00314 _M_variant._M_iterator._M_name = __name; 00315 _M_variant._M_iterator._M_address = std::__addressof(__it); 00316 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 00317 _M_variant._M_iterator._M_constness = __mutable_iterator; 00318 _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; 00319 _M_variant._M_iterator._M_sequence = 0; 00320 _M_variant._M_iterator._M_seq_type = 0; 00321 } 00322 00323 template<typename _Iterator> 00324 _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) 00325 : _M_kind(__iterator), _M_variant() 00326 { 00327 _M_variant._M_iterator._M_name = __name; 00328 _M_variant._M_iterator._M_address = std::__addressof(__it); 00329 _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); 00330 _M_variant._M_iterator._M_constness = __unknown_constness; 00331 _M_variant._M_iterator._M_state = 00332 __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; 00333 _M_variant._M_iterator._M_sequence = 0; 00334 _M_variant._M_iterator._M_seq_type = 0; 00335 } 00336 00337 template<typename _Sequence> 00338 _Parameter(const _Safe_sequence<_Sequence>& __seq, 00339 const char* __name, _Is_sequence) 00340 : _M_kind(__sequence), _M_variant() 00341 { 00342 _M_variant._M_sequence._M_name = __name; 00343 _M_variant._M_sequence._M_address = 00344 static_cast<const _Sequence*>(std::__addressof(__seq)); 00345 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 00346 } 00347 00348 template<typename _Sequence> 00349 _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 00350 : _M_kind(__sequence), _M_variant() 00351 { 00352 _M_variant._M_sequence._M_name = __name; 00353 _M_variant._M_sequence._M_address = std::__addressof(__seq); 00354 _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); 00355 } 00356 00357 template<typename _Iterator> 00358 _Parameter(const _Iterator& __it, const char* __name, 00359 _Is_iterator_value_type) 00360 : _M_kind(__iterator_value_type), _M_variant() 00361 { 00362 _M_variant._M_iterator_value_type._M_name = __name; 00363 _M_variant._M_iterator_value_type._M_type = 00364 _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); 00365 } 00366 00367 template<typename _Type> 00368 _Parameter(const _Type& __inst, const char* __name, _Is_instance) 00369 : _M_kind(__instance), _M_variant() 00370 { 00371 _M_variant._M_instance._M_name = __name; 00372 _M_variant._M_instance._M_address = &__inst; 00373 _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); 00374 } 00375 00376 #if !_GLIBCXX_INLINE_VERSION 00377 void 00378 _M_print_field(const _Error_formatter* __formatter, 00379 const char* __name) const _GLIBCXX_DEPRECATED; 00380 00381 void 00382 _M_print_description(const _Error_formatter* __formatter) 00383 const _GLIBCXX_DEPRECATED; 00384 #endif 00385 }; 00386 00387 template<typename _Iterator> 00388 _Error_formatter& 00389 _M_iterator(const _Iterator& __it, const char* __name = 0) 00390 { 00391 if (_M_num_parameters < std::size_t(__max_parameters)) 00392 _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 00393 _Is_iterator()); 00394 return *this; 00395 } 00396 00397 template<typename _Iterator> 00398 _Error_formatter& 00399 _M_iterator_value_type(const _Iterator& __it, 00400 const char* __name = 0) 00401 { 00402 if (_M_num_parameters < __max_parameters) 00403 _M_parameters[_M_num_parameters++] = 00404 _Parameter(__it, __name, _Is_iterator_value_type()); 00405 return *this; 00406 } 00407 00408 _Error_formatter& 00409 _M_integer(long __value, const char* __name = 0) 00410 { 00411 if (_M_num_parameters < __max_parameters) 00412 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 00413 return *this; 00414 } 00415 00416 _Error_formatter& 00417 _M_string(const char* __value, const char* __name = 0) 00418 { 00419 if (_M_num_parameters < __max_parameters) 00420 _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 00421 return *this; 00422 } 00423 00424 template<typename _Sequence> 00425 _Error_formatter& 00426 _M_sequence(const _Sequence& __seq, const char* __name = 0) 00427 { 00428 if (_M_num_parameters < __max_parameters) 00429 _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 00430 _Is_sequence()); 00431 return *this; 00432 } 00433 00434 template<typename _Type> 00435 _Error_formatter& 00436 _M_instance(const _Type& __inst, const char* __name = 0) 00437 { 00438 if (_M_num_parameters < __max_parameters) 00439 _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, 00440 _Is_instance()); 00441 return *this; 00442 } 00443 00444 _Error_formatter& 00445 _M_message(const char* __text) 00446 { _M_text = __text; return *this; } 00447 00448 // Kept const qualifier for backward compatibility, to keep the same 00449 // exported symbol. 00450 _Error_formatter& 00451 _M_message(_Debug_msg_id __id) const throw (); 00452 00453 _GLIBCXX_NORETURN void 00454 _M_error() const; 00455 00456 #if !_GLIBCXX_INLINE_VERSION 00457 template<typename _Tp> 00458 void 00459 _M_format_word(char*, int, const char*, _Tp) 00460 const throw () _GLIBCXX_DEPRECATED; 00461 00462 void 00463 _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; 00464 00465 void 00466 _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; 00467 #endif 00468 00469 private: 00470 _Error_formatter(const char* __file, unsigned int __line) 00471 : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) 00472 { } 00473 00474 #if !_GLIBCXX_INLINE_VERSION 00475 void 00476 _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; 00477 #endif 00478 00479 enum { __max_parameters = 9 }; 00480 00481 const char* _M_file; 00482 unsigned int _M_line; 00483 _Parameter _M_parameters[__max_parameters]; 00484 unsigned int _M_num_parameters; 00485 const char* _M_text; 00486 00487 public: 00488 static _Error_formatter& 00489 _M_at(const char* __file, unsigned int __line) 00490 { 00491 static _Error_formatter __formatter(__file, __line); 00492 return __formatter; 00493 } 00494 }; 00495 } // namespace __gnu_debug 00496 00497 #undef _GLIBCXX_TYPEID 00498 00499 #endif