libstdc++
formatter.h
Go to the documentation of this file.
00001 // Debug-mode error formatting implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2016 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       void
00377       _M_print_field(const _Error_formatter* __formatter,
00378                      const char* __name) const _GLIBCXX_DEPRECATED;
00379 
00380       void
00381       _M_print_description(const _Error_formatter* __formatter)
00382         const _GLIBCXX_DEPRECATED;
00383     };
00384 
00385     template<typename _Iterator>
00386       _Error_formatter&
00387       _M_iterator(const _Iterator& __it, const char* __name = 0)
00388       {
00389         if (_M_num_parameters < std::size_t(__max_parameters))
00390           _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
00391                                                           _Is_iterator());
00392         return *this;
00393       }
00394 
00395     template<typename _Iterator>
00396       _Error_formatter&
00397       _M_iterator_value_type(const _Iterator& __it,
00398                              const char* __name = 0)
00399       {
00400         if (_M_num_parameters < __max_parameters)
00401           _M_parameters[_M_num_parameters++] =
00402             _Parameter(__it, __name, _Is_iterator_value_type());
00403         return *this;
00404       }
00405 
00406     _Error_formatter&
00407     _M_integer(long __value, const char* __name = 0)
00408     {
00409       if (_M_num_parameters < __max_parameters)
00410         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
00411       return *this;
00412     }
00413 
00414     _Error_formatter&
00415     _M_string(const char* __value, const char* __name = 0)
00416     {
00417       if (_M_num_parameters < __max_parameters)
00418         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
00419       return *this;
00420     }
00421 
00422     template<typename _Sequence>
00423       _Error_formatter&
00424       _M_sequence(const _Sequence& __seq, const char* __name = 0)
00425       {
00426         if (_M_num_parameters < __max_parameters)
00427           _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
00428                                                           _Is_sequence());
00429         return *this;
00430       }
00431 
00432     template<typename _Type>
00433       _Error_formatter&
00434       _M_instance(const _Type& __inst, const char* __name = 0)
00435       {
00436         if (_M_num_parameters < __max_parameters)
00437           _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
00438                                                           _Is_instance());
00439         return *this;
00440       }
00441 
00442     _Error_formatter&
00443     _M_message(const char* __text)
00444     { _M_text = __text; return *this; }
00445 
00446     // Kept const qualifier for backward compatibility, to keep the same
00447     // exported symbol.
00448     _Error_formatter&
00449     _M_message(_Debug_msg_id __id) const throw ();
00450 
00451     _GLIBCXX_NORETURN void
00452     _M_error() const;
00453 
00454     template<typename _Tp>
00455       void
00456       _M_format_word(char*, int, const char*, _Tp)
00457       const throw () _GLIBCXX_DEPRECATED;
00458 
00459     void
00460     _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED;
00461 
00462     void
00463     _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED;
00464 
00465   private:
00466     _Error_formatter(const char* __file, unsigned int __line)
00467     : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0)
00468     { }
00469 
00470     void
00471     _M_get_max_length() const throw () _GLIBCXX_DEPRECATED;
00472 
00473     enum { __max_parameters = 9 };
00474 
00475     const char*         _M_file;
00476     unsigned int        _M_line;
00477     _Parameter          _M_parameters[__max_parameters];
00478     unsigned int        _M_num_parameters;
00479     const char*         _M_text;
00480 
00481   public:
00482     static _Error_formatter&
00483     _M_at(const char* __file, unsigned int __line)
00484     {
00485       static _Error_formatter __formatter(__file, __line);
00486       return __formatter;
00487     }
00488   };
00489 } // namespace __gnu_debug
00490 
00491 #undef _GLIBCXX_TYPEID
00492 
00493 #endif