libstdc++
formatter.h
Go to the documentation of this file.
00001 // Debug-mode error formatting implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2019 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 
00034 #if __cpp_rtti
00035 # include <typeinfo>
00036 # define _GLIBCXX_TYPEID(_Type) &typeid(_Type)
00037 #else
00038 namespace std
00039 {
00040   class type_info;
00041 }
00042 # define _GLIBCXX_TYPEID(_Type) 0
00043 #endif
00044 
00045 #if __cplusplus >= 201103L
00046 namespace __gnu_cxx
00047 {
00048 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00049 
00050 template<typename _Iterator, typename _Container>
00051   class __normal_iterator;
00052 
00053 _GLIBCXX_END_NAMESPACE_VERSION
00054 }
00055 
00056 namespace std
00057 {
00058 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00059 
00060 template<typename _Iterator>
00061   class reverse_iterator;
00062 
00063 template<typename _Iterator>
00064   class move_iterator;
00065 
00066 _GLIBCXX_END_NAMESPACE_VERSION
00067 }
00068 #endif
00069 
00070 namespace __gnu_debug
00071 {
00072   using std::type_info;
00073 
00074   template<typename _Iterator>
00075     bool __check_singular(const _Iterator&);
00076 
00077   class _Safe_sequence_base;
00078 
00079   template<typename _Iterator, typename _Sequence, typename _Category>
00080     class _Safe_iterator;
00081 
00082   template<typename _Iterator, typename _Sequence>
00083     class _Safe_local_iterator;
00084 
00085   template<typename _Sequence>
00086     class _Safe_sequence;
00087 
00088   enum _Debug_msg_id
00089   {
00090     // General checks
00091     __msg_valid_range,
00092     __msg_insert_singular,
00093     __msg_insert_different,
00094     __msg_erase_bad,
00095     __msg_erase_different,
00096     __msg_subscript_oob,
00097     __msg_empty,
00098     __msg_unpartitioned,
00099     __msg_unpartitioned_pred,
00100     __msg_unsorted,
00101     __msg_unsorted_pred,
00102     __msg_not_heap,
00103     __msg_not_heap_pred,
00104     // std::bitset checks
00105     __msg_bad_bitset_write,
00106     __msg_bad_bitset_read,
00107     __msg_bad_bitset_flip,
00108     // std::list checks
00109     __msg_self_splice,
00110     __msg_splice_alloc,
00111     __msg_splice_bad,
00112     __msg_splice_other,
00113     __msg_splice_overlap,
00114     // iterator checks
00115     __msg_init_singular,
00116     __msg_init_copy_singular,
00117     __msg_init_const_singular,
00118     __msg_copy_singular,
00119     __msg_bad_deref,
00120     __msg_bad_inc,
00121     __msg_bad_dec,
00122     __msg_iter_subscript_oob,
00123     __msg_advance_oob,
00124     __msg_retreat_oob,
00125     __msg_iter_compare_bad,
00126     __msg_compare_different,
00127     __msg_iter_order_bad,
00128     __msg_order_different,
00129     __msg_distance_bad,
00130     __msg_distance_different,
00131     // istream_iterator
00132     __msg_deref_istream,
00133     __msg_inc_istream,
00134     // ostream_iterator
00135     __msg_output_ostream,
00136     // istreambuf_iterator
00137     __msg_deref_istreambuf,
00138     __msg_inc_istreambuf,
00139     // forward_list
00140     __msg_insert_after_end,
00141     __msg_erase_after_bad,
00142     __msg_valid_range2,
00143     // unordered container local iterators
00144     __msg_local_iter_compare_bad,
00145     __msg_non_empty_range,
00146     // self move assign
00147     __msg_self_move_assign,
00148     // unordered container buckets
00149     __msg_bucket_index_oob,
00150     __msg_valid_load_factor,
00151     // others
00152     __msg_equal_allocs,
00153     __msg_insert_range_from_self,
00154     __msg_irreflexive_ordering
00155   };
00156 
00157   class _Error_formatter
00158   {
00159     // Tags denoting the type of parameter for construction
00160     struct _Is_iterator { };
00161     struct _Is_iterator_value_type { };
00162     struct _Is_sequence { };
00163     struct _Is_instance { };
00164 
00165   public:
00166     /// Whether an iterator is constant, mutable, or unknown
00167     enum _Constness
00168     {
00169       __unknown_constness,
00170       __const_iterator,
00171       __mutable_iterator,
00172       __last_constness
00173     };
00174 
00175     // The state of the iterator (fine-grained), if we know it.
00176     enum _Iterator_state
00177     {
00178       __unknown_state,
00179       __singular,       // singular, may still be attached to a sequence
00180       __begin,          // dereferenceable, and at the beginning
00181       __middle,         // dereferenceable, not at the beginning
00182       __end,            // past-the-end, may be at beginning if sequence empty
00183       __before_begin,   // before begin
00184       __rbegin,         // dereferenceable, and at the reverse-beginning
00185       __rmiddle,        // reverse-dereferenceable, not at the reverse-beginning
00186       __rend,           // reverse-past-the-end
00187       __last_state
00188     };
00189 
00190     // A parameter that may be referenced by an error message
00191     struct _Parameter
00192     {
00193       enum
00194       {
00195         __unused_param,
00196         __iterator,
00197         __sequence,
00198         __integer,
00199         __string,
00200         __instance,
00201         __iterator_value_type
00202       } _M_kind;
00203 
00204       struct _Type
00205       {
00206         const char*             _M_name;
00207         const type_info*        _M_type;
00208       };
00209 
00210       struct _Instance : _Type
00211       {
00212         const void*             _M_address;
00213       };
00214 
00215       union
00216       {
00217         // When _M_kind == __iterator
00218         struct : _Instance
00219         {
00220           _Constness            _M_constness;
00221           _Iterator_state       _M_state;
00222           const void*           _M_sequence;
00223           const type_info*      _M_seq_type;
00224         } _M_iterator;
00225 
00226         // When _M_kind == __sequence
00227         _Instance _M_sequence;
00228 
00229         // When _M_kind == __integer
00230         struct
00231         {
00232           const char*           _M_name;
00233           long                  _M_value;
00234         } _M_integer;
00235 
00236         // When _M_kind == __string
00237         struct
00238         {
00239           const char*           _M_name;
00240           const char*           _M_value;
00241         } _M_string;
00242 
00243         // When _M_kind == __instance
00244         _Instance _M_instance;
00245 
00246         // When _M_kind == __iterator_value_type
00247         _Type _M_iterator_value_type;
00248       } _M_variant;
00249 
00250       _Parameter() : _M_kind(__unused_param), _M_variant() { }
00251 
00252       _Parameter(long __value, const char* __name)
00253       : _M_kind(__integer), _M_variant()
00254       {
00255         _M_variant._M_integer._M_name = __name;
00256         _M_variant._M_integer._M_value = __value;
00257       }
00258 
00259       _Parameter(const char* __value, const char* __name)
00260       : _M_kind(__string), _M_variant()
00261       {
00262         _M_variant._M_string._M_name = __name;
00263         _M_variant._M_string._M_value = __value;
00264       }
00265 
00266       template<typename _Iterator, typename _Sequence, typename _Category>
00267         _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it,
00268                    const char* __name, _Is_iterator)
00269         : _M_kind(__iterator),  _M_variant()
00270         {
00271           _M_variant._M_iterator._M_name = __name;
00272           _M_variant._M_iterator._M_address = std::__addressof(__it);
00273           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
00274           _M_variant._M_iterator._M_constness =
00275             __it._S_constant() ? __const_iterator : __mutable_iterator;
00276           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
00277           _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
00278 
00279           if (__it._M_singular())
00280             _M_variant._M_iterator._M_state = __singular;
00281           else
00282             {
00283               if (__it._M_is_before_begin())
00284                 _M_variant._M_iterator._M_state = __before_begin;
00285               else if (__it._M_is_end())
00286                 _M_variant._M_iterator._M_state = __end;
00287               else if (__it._M_is_begin())
00288                 _M_variant._M_iterator._M_state = __begin;
00289               else
00290                 _M_variant._M_iterator._M_state = __middle;
00291             }
00292         }
00293 
00294       template<typename _Iterator, typename _Sequence>
00295         _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it,
00296                    const char* __name, _Is_iterator)
00297         : _M_kind(__iterator),  _M_variant()
00298         {
00299           _M_variant._M_iterator._M_name = __name;
00300           _M_variant._M_iterator._M_address = std::__addressof(__it);
00301           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator);
00302           _M_variant._M_iterator._M_constness =
00303           _M_variant._M_iterator._M_constness =
00304             __it._S_constant() ? __const_iterator : __mutable_iterator;
00305           _M_variant._M_iterator._M_sequence = __it._M_get_sequence();
00306           _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence);
00307 
00308           if (__it._M_singular())
00309             _M_variant._M_iterator._M_state = __singular;
00310           else
00311             {
00312               if (__it._M_is_end())
00313                 _M_variant._M_iterator._M_state = __end;
00314               else if (__it._M_is_begin())
00315                 _M_variant._M_iterator._M_state = __begin;
00316               else
00317                 _M_variant._M_iterator._M_state = __middle;
00318             }
00319         }
00320 
00321       template<typename _Type>
00322         _Parameter(const _Type* const& __it, const char* __name, _Is_iterator)
00323         : _M_kind(__iterator), _M_variant()
00324         {
00325           _M_variant._M_iterator._M_name = __name;
00326           _M_variant._M_iterator._M_address = std::__addressof(__it);
00327           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
00328           _M_variant._M_iterator._M_constness = __const_iterator;
00329           _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
00330           _M_variant._M_iterator._M_sequence = 0;
00331           _M_variant._M_iterator._M_seq_type = 0;
00332         }
00333 
00334       template<typename _Type>
00335         _Parameter(_Type* const& __it, const char* __name, _Is_iterator)
00336         : _M_kind(__iterator), _M_variant()
00337         {
00338           _M_variant._M_iterator._M_name = __name;
00339           _M_variant._M_iterator._M_address = std::__addressof(__it);
00340           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
00341           _M_variant._M_iterator._M_constness = __mutable_iterator;
00342           _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular;
00343           _M_variant._M_iterator._M_sequence = 0;
00344           _M_variant._M_iterator._M_seq_type = 0;
00345         }
00346 
00347       template<typename _Iterator>
00348         _Parameter(_Iterator const& __it, const char* __name, _Is_iterator)
00349         : _M_kind(__iterator), _M_variant()
00350         {
00351           _M_variant._M_iterator._M_name = __name;
00352           _M_variant._M_iterator._M_address = std::__addressof(__it);
00353           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
00354           _M_variant._M_iterator._M_constness = __unknown_constness;
00355           _M_variant._M_iterator._M_state =
00356             __gnu_debug::__check_singular(__it) ? __singular : __unknown_state;
00357           _M_variant._M_iterator._M_sequence = 0;
00358           _M_variant._M_iterator._M_seq_type = 0;
00359         }
00360 
00361 #if __cplusplus >= 201103L
00362       // The following constructors are only defined in C++11 to take
00363       // advantage of the constructor delegation feature.
00364       template<typename _Iterator, typename _Container>
00365         _Parameter(
00366           __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it,
00367         const char* __name, _Is_iterator)
00368         : _Parameter(__it.base(), __name, _Is_iterator{})
00369         { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
00370 
00371       template<typename _Iterator>
00372         _Parameter(std::reverse_iterator<_Iterator> const& __it,
00373                    const char* __name, _Is_iterator)
00374         : _Parameter(__it.base(), __name, _Is_iterator{})
00375         {
00376           _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it);
00377           _M_variant._M_iterator._M_state
00378             = _S_reverse_state(_M_variant._M_iterator._M_state);
00379         }
00380 
00381       template<typename _Iterator, typename _Sequence, typename _Category>
00382         _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence,
00383                                                         _Category>> const& __it,
00384           const char* __name, _Is_iterator)
00385         : _Parameter(__it.base(), __name, _Is_iterator{})
00386         {
00387           _M_variant._M_iterator._M_type
00388             = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>);
00389           _M_variant._M_iterator._M_state
00390             = _S_reverse_state(_M_variant._M_iterator._M_state);
00391         }
00392 
00393       template<typename _Iterator>
00394         _Parameter(std::move_iterator<_Iterator> const& __it,
00395                    const char* __name, _Is_iterator)
00396         : _Parameter(__it.base(), __name, _Is_iterator{})
00397         { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
00398 
00399       template<typename _Iterator, typename _Sequence, typename _Category>
00400         _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence,
00401                                                      _Category>> const& __it,
00402           const char* __name, _Is_iterator)
00403         : _Parameter(__it.base(), __name, _Is_iterator{})
00404       {
00405         _M_variant._M_iterator._M_type
00406           = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>);
00407       }
00408 
00409     private:
00410       _Iterator_state
00411       _S_reverse_state(_Iterator_state __state)
00412       {
00413           switch (__state)
00414             {
00415             case __begin:
00416               return __rend;
00417             case __middle:
00418               return __rmiddle;
00419             case __end:
00420               return __rbegin;
00421             default:
00422               return __state;
00423             }
00424       }
00425 
00426     public:
00427 #endif
00428 
00429       template<typename _Sequence>
00430         _Parameter(const _Safe_sequence<_Sequence>& __seq,
00431                    const char* __name, _Is_sequence)
00432         : _M_kind(__sequence), _M_variant()
00433         {
00434           _M_variant._M_sequence._M_name = __name;
00435           _M_variant._M_sequence._M_address =
00436             static_cast<const _Sequence*>(std::__addressof(__seq));
00437           _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
00438         }
00439 
00440       template<typename _Sequence>
00441         _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence)
00442         : _M_kind(__sequence), _M_variant()
00443         {
00444           _M_variant._M_sequence._M_name = __name;
00445           _M_variant._M_sequence._M_address = std::__addressof(__seq);
00446           _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence);
00447         }
00448 
00449       template<typename _Iterator>
00450         _Parameter(const _Iterator& __it, const char* __name,
00451                    _Is_iterator_value_type)
00452         : _M_kind(__iterator_value_type), _M_variant()
00453         {
00454           _M_variant._M_iterator_value_type._M_name = __name;
00455           _M_variant._M_iterator_value_type._M_type =
00456             _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type);
00457         }
00458 
00459       template<typename _Type>
00460         _Parameter(const _Type& __inst, const char* __name, _Is_instance)
00461         : _M_kind(__instance), _M_variant()
00462         {
00463           _M_variant._M_instance._M_name = __name;
00464           _M_variant._M_instance._M_address = &__inst;
00465           _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type);
00466         }
00467 
00468 #if !_GLIBCXX_INLINE_VERSION
00469       void
00470       _M_print_field(const _Error_formatter* __formatter,
00471                      const char* __name) const _GLIBCXX_DEPRECATED;
00472 
00473       void
00474       _M_print_description(const _Error_formatter* __formatter)
00475         const _GLIBCXX_DEPRECATED;
00476 #endif
00477     };
00478 
00479     template<typename _Iterator>
00480       _Error_formatter&
00481       _M_iterator(const _Iterator& __it, const char* __name = 0)
00482       {
00483         if (_M_num_parameters < std::size_t(__max_parameters))
00484           _M_parameters[_M_num_parameters++] = _Parameter(__it, __name,
00485                                                           _Is_iterator());
00486         return *this;
00487       }
00488 
00489     template<typename _Iterator>
00490       _Error_formatter&
00491       _M_iterator_value_type(const _Iterator& __it,
00492                              const char* __name = 0)
00493       {
00494         if (_M_num_parameters < __max_parameters)
00495           _M_parameters[_M_num_parameters++] =
00496             _Parameter(__it, __name, _Is_iterator_value_type());
00497         return *this;
00498       }
00499 
00500     _Error_formatter&
00501     _M_integer(long __value, const char* __name = 0)
00502     {
00503       if (_M_num_parameters < __max_parameters)
00504         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
00505       return *this;
00506     }
00507 
00508     _Error_formatter&
00509     _M_string(const char* __value, const char* __name = 0)
00510     {
00511       if (_M_num_parameters < __max_parameters)
00512         _M_parameters[_M_num_parameters++] = _Parameter(__value, __name);
00513       return *this;
00514     }
00515 
00516     template<typename _Sequence>
00517       _Error_formatter&
00518       _M_sequence(const _Sequence& __seq, const char* __name = 0)
00519       {
00520         if (_M_num_parameters < __max_parameters)
00521           _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name,
00522                                                           _Is_sequence());
00523         return *this;
00524       }
00525 
00526     template<typename _Type>
00527       _Error_formatter&
00528       _M_instance(const _Type& __inst, const char* __name = 0)
00529       {
00530         if (_M_num_parameters < __max_parameters)
00531           _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name,
00532                                                           _Is_instance());
00533         return *this;
00534       }
00535 
00536     _Error_formatter&
00537     _M_message(const char* __text)
00538     { _M_text = __text; return *this; }
00539 
00540     // Kept const qualifier for backward compatibility, to keep the same
00541     // exported symbol.
00542     _Error_formatter&
00543     _M_message(_Debug_msg_id __id) const throw ();
00544 
00545     _GLIBCXX_NORETURN void
00546     _M_error() const;
00547 
00548 #if !_GLIBCXX_INLINE_VERSION
00549     template<typename _Tp>
00550       void
00551       _M_format_word(char*, int, const char*, _Tp)
00552       const throw () _GLIBCXX_DEPRECATED;
00553 
00554     void
00555     _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED;
00556 
00557     void
00558     _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED;
00559 #endif
00560 
00561   private:
00562     _Error_formatter(const char* __file, unsigned int __line,
00563                      const char* __function)
00564     : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0)
00565     , _M_function(__function)
00566     { }
00567 
00568 #if !_GLIBCXX_INLINE_VERSION
00569     void
00570     _M_get_max_length() const throw () _GLIBCXX_DEPRECATED;
00571 #endif
00572 
00573     enum { __max_parameters = 9 };
00574 
00575     const char*         _M_file;
00576     unsigned int        _M_line;
00577     _Parameter          _M_parameters[__max_parameters];
00578     unsigned int        _M_num_parameters;
00579     const char*         _M_text;
00580     const char*         _M_function;
00581 
00582   public:
00583     static _Error_formatter&
00584     _S_at(const char* __file, unsigned int __line, const char* __function)
00585     {
00586       static _Error_formatter __formatter(__file, __line, __function);
00587       return __formatter;
00588     }
00589   };
00590 } // namespace __gnu_debug
00591 
00592 #undef _GLIBCXX_TYPEID
00593 
00594 #endif