1*38fd1498Szrj // Debugging mode support code -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj // Copyright (C) 2003-2018 Free Software Foundation, Inc. 4*38fd1498Szrj // 5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj // software; you can redistribute it and/or modify it under the 7*38fd1498Szrj // terms of the GNU General Public License as published by the 8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option) 9*38fd1498Szrj // any later version. 10*38fd1498Szrj 11*38fd1498Szrj // This library is distributed in the hope that it will be useful, 12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*38fd1498Szrj // GNU General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj // 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj // You should have received a copy of the GNU General Public License and 21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj // <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj #include <bits/move.h> 26*38fd1498Szrj #include <bits/stl_iterator_base_types.h> 27*38fd1498Szrj 28*38fd1498Szrj #include <debug/formatter.h> 29*38fd1498Szrj #include <debug/safe_base.h> 30*38fd1498Szrj #include <debug/safe_unordered_base.h> 31*38fd1498Szrj #include <debug/safe_iterator.h> 32*38fd1498Szrj #include <debug/safe_local_iterator.h> 33*38fd1498Szrj #include <debug/vector> 34*38fd1498Szrj 35*38fd1498Szrj #include <cassert> 36*38fd1498Szrj #include <cstdio> 37*38fd1498Szrj #include <cctype> // for std::isspace 38*38fd1498Szrj 39*38fd1498Szrj #include <algorithm> // for std::min 40*38fd1498Szrj 41*38fd1498Szrj #include <cxxabi.h> // for __cxa_demangle 42*38fd1498Szrj 43*38fd1498Szrj #include "mutex_pool.h" 44*38fd1498Szrj 45*38fd1498Szrj using namespace std; 46*38fd1498Szrj 47*38fd1498Szrj namespace 48*38fd1498Szrj { 49*38fd1498Szrj /** Returns different instances of __mutex depending on the passed address 50*38fd1498Szrj * in order to limit contention without breaking current library binary 51*38fd1498Szrj * compatibility. */ 52*38fd1498Szrj __gnu_cxx::__mutex& get_safe_base_mutex(void * address)53*38fd1498Szrj get_safe_base_mutex(void* address) 54*38fd1498Szrj { 55*38fd1498Szrj // Use arbitrarily __gnu_debug::vector<int> as the container giving 56*38fd1498Szrj // alignment of debug containers. 57*38fd1498Szrj const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector<int>)); 58*38fd1498Szrj const unsigned char index 59*38fd1498Szrj = (reinterpret_cast<std::size_t>(address) >> alignbits) 60*38fd1498Szrj & __gnu_internal::mask; 61*38fd1498Szrj return __gnu_internal::get_mutex(index); 62*38fd1498Szrj } 63*38fd1498Szrj 64*38fd1498Szrj void swap_its(__gnu_debug::_Safe_sequence_base & __lhs,__gnu_debug::_Safe_iterator_base * & __lhs_its,__gnu_debug::_Safe_sequence_base & __rhs,__gnu_debug::_Safe_iterator_base * & __rhs_its)65*38fd1498Szrj swap_its(__gnu_debug::_Safe_sequence_base& __lhs, 66*38fd1498Szrj __gnu_debug::_Safe_iterator_base*& __lhs_its, 67*38fd1498Szrj __gnu_debug::_Safe_sequence_base& __rhs, 68*38fd1498Szrj __gnu_debug::_Safe_iterator_base*& __rhs_its) 69*38fd1498Szrj { 70*38fd1498Szrj swap(__lhs_its, __rhs_its); 71*38fd1498Szrj __gnu_debug::_Safe_iterator_base* __iter; 72*38fd1498Szrj for (__iter = __rhs_its; __iter; __iter = __iter->_M_next) 73*38fd1498Szrj __iter->_M_sequence = &__rhs; 74*38fd1498Szrj for (__iter = __lhs_its; __iter; __iter = __iter->_M_next) 75*38fd1498Szrj __iter->_M_sequence = &__lhs; 76*38fd1498Szrj } 77*38fd1498Szrj 78*38fd1498Szrj void swap_seq_single(__gnu_debug::_Safe_sequence_base & __lhs,__gnu_debug::_Safe_sequence_base & __rhs)79*38fd1498Szrj swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs, 80*38fd1498Szrj __gnu_debug::_Safe_sequence_base& __rhs) 81*38fd1498Szrj { 82*38fd1498Szrj swap(__lhs._M_version, __rhs._M_version); 83*38fd1498Szrj swap_its(__lhs, __lhs._M_iterators, 84*38fd1498Szrj __rhs, __rhs._M_iterators); 85*38fd1498Szrj swap_its(__lhs, __lhs._M_const_iterators, 86*38fd1498Szrj __rhs, __rhs._M_const_iterators); 87*38fd1498Szrj } 88*38fd1498Szrj 89*38fd1498Szrj template<typename _Action> 90*38fd1498Szrj void lock_and_run(__gnu_cxx::__mutex & lhs_mutex,__gnu_cxx::__mutex & rhs_mutex,_Action action)91*38fd1498Szrj lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex, 92*38fd1498Szrj _Action action) 93*38fd1498Szrj { 94*38fd1498Szrj // We need to lock both sequences to run action. 95*38fd1498Szrj if (&lhs_mutex == &rhs_mutex) 96*38fd1498Szrj { 97*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(lhs_mutex); 98*38fd1498Szrj action(); 99*38fd1498Szrj } 100*38fd1498Szrj else 101*38fd1498Szrj { 102*38fd1498Szrj __gnu_cxx::__scoped_lock sentry1(&lhs_mutex < &rhs_mutex 103*38fd1498Szrj ? lhs_mutex : rhs_mutex); 104*38fd1498Szrj __gnu_cxx::__scoped_lock sentry2(&lhs_mutex < &rhs_mutex 105*38fd1498Szrj ? rhs_mutex : lhs_mutex); 106*38fd1498Szrj action(); 107*38fd1498Szrj } 108*38fd1498Szrj } 109*38fd1498Szrj 110*38fd1498Szrj void swap_seq(__gnu_cxx::__mutex & lhs_mutex,__gnu_debug::_Safe_sequence_base & lhs,__gnu_cxx::__mutex & rhs_mutex,__gnu_debug::_Safe_sequence_base & rhs)111*38fd1498Szrj swap_seq(__gnu_cxx::__mutex& lhs_mutex, 112*38fd1498Szrj __gnu_debug::_Safe_sequence_base& lhs, 113*38fd1498Szrj __gnu_cxx::__mutex& rhs_mutex, 114*38fd1498Szrj __gnu_debug::_Safe_sequence_base& rhs) 115*38fd1498Szrj { 116*38fd1498Szrj lock_and_run(lhs_mutex, rhs_mutex, 117*38fd1498Szrj [&lhs, &rhs]() { swap_seq_single(lhs, rhs); }); 118*38fd1498Szrj } 119*38fd1498Szrj 120*38fd1498Szrj void swap_ucont_single(__gnu_debug::_Safe_unordered_container_base & __lhs,__gnu_debug::_Safe_unordered_container_base & __rhs)121*38fd1498Szrj swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs, 122*38fd1498Szrj __gnu_debug::_Safe_unordered_container_base& __rhs) 123*38fd1498Szrj { 124*38fd1498Szrj swap_seq_single(__lhs, __rhs); 125*38fd1498Szrj swap_its(__lhs, __lhs._M_local_iterators, 126*38fd1498Szrj __rhs, __rhs._M_local_iterators); 127*38fd1498Szrj swap_its(__lhs, __lhs._M_const_local_iterators, 128*38fd1498Szrj __rhs, __rhs._M_const_local_iterators); 129*38fd1498Szrj } 130*38fd1498Szrj 131*38fd1498Szrj void swap_ucont(__gnu_cxx::__mutex & lhs_mutex,__gnu_debug::_Safe_unordered_container_base & lhs,__gnu_cxx::__mutex & rhs_mutex,__gnu_debug::_Safe_unordered_container_base & rhs)132*38fd1498Szrj swap_ucont(__gnu_cxx::__mutex& lhs_mutex, 133*38fd1498Szrj __gnu_debug::_Safe_unordered_container_base& lhs, 134*38fd1498Szrj __gnu_cxx::__mutex& rhs_mutex, 135*38fd1498Szrj __gnu_debug::_Safe_unordered_container_base& rhs) 136*38fd1498Szrj { 137*38fd1498Szrj lock_and_run(lhs_mutex, rhs_mutex, 138*38fd1498Szrj [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); }); 139*38fd1498Szrj } 140*38fd1498Szrj 141*38fd1498Szrj void detach_all(__gnu_debug::_Safe_iterator_base * __iter)142*38fd1498Szrj detach_all(__gnu_debug::_Safe_iterator_base* __iter) 143*38fd1498Szrj { 144*38fd1498Szrj for (; __iter;) 145*38fd1498Szrj { 146*38fd1498Szrj __gnu_debug::_Safe_iterator_base* __old = __iter; 147*38fd1498Szrj __iter = __iter->_M_next; 148*38fd1498Szrj __old->_M_reset(); 149*38fd1498Szrj } 150*38fd1498Szrj } 151*38fd1498Szrj } // anonymous namespace 152*38fd1498Szrj 153*38fd1498Szrj namespace __gnu_debug 154*38fd1498Szrj { 155*38fd1498Szrj const char* const _S_debug_messages[] = 156*38fd1498Szrj { 157*38fd1498Szrj // General Checks 158*38fd1498Szrj "function requires a valid iterator range [%1.name;, %2.name;)", 159*38fd1498Szrj "attempt to insert into container with a singular iterator", 160*38fd1498Szrj "attempt to insert into container with an iterator" 161*38fd1498Szrj " from a different container", 162*38fd1498Szrj "attempt to erase from container with a %2.state; iterator", 163*38fd1498Szrj "attempt to erase from container with an iterator" 164*38fd1498Szrj " from a different container", 165*38fd1498Szrj "attempt to subscript container with out-of-bounds index %2;," 166*38fd1498Szrj " but container only holds %3; elements", 167*38fd1498Szrj "attempt to access an element in an empty container", 168*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;)" 169*38fd1498Szrj " are not partitioned by the value %3;", 170*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;)" 171*38fd1498Szrj " are not partitioned by the predicate %3; and value %4;", 172*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;) are not sorted", 173*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;)" 174*38fd1498Szrj " are not sorted according to the predicate %3;", 175*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;) do not form a heap", 176*38fd1498Szrj "elements in iterator range [%1.name;, %2.name;)" 177*38fd1498Szrj " do not form a heap with respect to the predicate %3;", 178*38fd1498Szrj // std::bitset checks 179*38fd1498Szrj "attempt to write through a singular bitset reference", 180*38fd1498Szrj "attempt to read from a singular bitset reference", 181*38fd1498Szrj "attempt to flip a singular bitset reference", 182*38fd1498Szrj // std::list checks 183*38fd1498Szrj "attempt to splice a list into itself", 184*38fd1498Szrj "attempt to splice lists with unequal allocators", 185*38fd1498Szrj "attempt to splice elements referenced by a %1.state; iterator", 186*38fd1498Szrj "attempt to splice an iterator from a different container", 187*38fd1498Szrj "splice destination %1.name;" 188*38fd1498Szrj " occurs within source range [%2.name;, %3.name;)", 189*38fd1498Szrj // iterator checks 190*38fd1498Szrj "attempt to initialize an iterator that will immediately become singular", 191*38fd1498Szrj "attempt to copy-construct an iterator from a singular iterator", 192*38fd1498Szrj "attempt to construct a constant iterator" 193*38fd1498Szrj " from a singular mutable iterator", 194*38fd1498Szrj "attempt to copy from a singular iterator", 195*38fd1498Szrj "attempt to dereference a %1.state; iterator", 196*38fd1498Szrj "attempt to increment a %1.state; iterator", 197*38fd1498Szrj "attempt to decrement a %1.state; iterator", 198*38fd1498Szrj "attempt to subscript a %1.state; iterator %2; step from" 199*38fd1498Szrj " its current position, which falls outside its dereferenceable range", 200*38fd1498Szrj "attempt to advance a %1.state; iterator %2; steps," 201*38fd1498Szrj " which falls outside its valid range", 202*38fd1498Szrj "attempt to retreat a %1.state; iterator %2; steps," 203*38fd1498Szrj " which falls outside its valid range", 204*38fd1498Szrj "attempt to compare a %1.state; iterator to a %2.state; iterator", 205*38fd1498Szrj "attempt to compare iterators from different sequences", 206*38fd1498Szrj "attempt to order a %1.state; iterator to a %2.state; iterator", 207*38fd1498Szrj "attempt to order iterators from different sequences", 208*38fd1498Szrj "attempt to compute the difference between a %1.state;" 209*38fd1498Szrj " iterator to a %2.state; iterator", 210*38fd1498Szrj "attempt to compute the different between two iterators" 211*38fd1498Szrj " from different sequences", 212*38fd1498Szrj // istream_iterator 213*38fd1498Szrj "attempt to dereference an end-of-stream istream_iterator", 214*38fd1498Szrj "attempt to increment an end-of-stream istream_iterator", 215*38fd1498Szrj // ostream_iterator 216*38fd1498Szrj "attempt to output via an ostream_iterator with no associated stream", 217*38fd1498Szrj // istreambuf_iterator 218*38fd1498Szrj "attempt to dereference an end-of-stream istreambuf_iterator" 219*38fd1498Szrj " (this is a GNU extension)", 220*38fd1498Szrj "attempt to increment an end-of-stream istreambuf_iterator", 221*38fd1498Szrj // std::forward_list 222*38fd1498Szrj "attempt to insert into container after an end iterator", 223*38fd1498Szrj "attempt to erase from container after a %2.state; iterator not followed" 224*38fd1498Szrj " by a dereferenceable one", 225*38fd1498Szrj "function requires a valid iterator range (%2.name;, %3.name;)" 226*38fd1498Szrj ", \"%2.name;\" shall be before and not equal to \"%3.name;\"", 227*38fd1498Szrj // std::unordered_container::local_iterator 228*38fd1498Szrj "attempt to compare local iterators from different unordered container" 229*38fd1498Szrj " buckets", 230*38fd1498Szrj "function requires a non-empty iterator range [%1.name;, %2.name;)", 231*38fd1498Szrj "attempt to self move assign", 232*38fd1498Szrj "attempt to access container with out-of-bounds bucket index %2;," 233*38fd1498Szrj " container only holds %3; buckets", 234*38fd1498Szrj "load factor shall be positive", 235*38fd1498Szrj "allocators must be equal", 236*38fd1498Szrj "attempt to insert with an iterator range [%1.name;, %2.name;) from this" 237*38fd1498Szrj " container", 238*38fd1498Szrj "comparison doesn't meet irreflexive requirements, assert(!(a < a))" 239*38fd1498Szrj }; 240*38fd1498Szrj 241*38fd1498Szrj void 242*38fd1498Szrj _Safe_sequence_base:: _M_detach_all()243*38fd1498Szrj _M_detach_all() 244*38fd1498Szrj { 245*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 246*38fd1498Szrj detach_all(_M_iterators); 247*38fd1498Szrj _M_iterators = 0; 248*38fd1498Szrj 249*38fd1498Szrj detach_all(_M_const_iterators); 250*38fd1498Szrj _M_const_iterators = 0; 251*38fd1498Szrj } 252*38fd1498Szrj 253*38fd1498Szrj void 254*38fd1498Szrj _Safe_sequence_base:: _M_detach_singular()255*38fd1498Szrj _M_detach_singular() 256*38fd1498Szrj { 257*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 258*38fd1498Szrj for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 259*38fd1498Szrj { 260*38fd1498Szrj _Safe_iterator_base* __old = __iter; 261*38fd1498Szrj __iter = __iter->_M_next; 262*38fd1498Szrj if (__old->_M_singular()) 263*38fd1498Szrj __old->_M_detach_single(); 264*38fd1498Szrj } 265*38fd1498Szrj 266*38fd1498Szrj for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 267*38fd1498Szrj { 268*38fd1498Szrj _Safe_iterator_base* __old = __iter2; 269*38fd1498Szrj __iter2 = __iter2->_M_next; 270*38fd1498Szrj if (__old->_M_singular()) 271*38fd1498Szrj __old->_M_detach_single(); 272*38fd1498Szrj } 273*38fd1498Szrj } 274*38fd1498Szrj 275*38fd1498Szrj void 276*38fd1498Szrj _Safe_sequence_base:: _M_revalidate_singular()277*38fd1498Szrj _M_revalidate_singular() 278*38fd1498Szrj { 279*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 280*38fd1498Szrj for (_Safe_iterator_base* __iter = _M_iterators; __iter; 281*38fd1498Szrj __iter = __iter->_M_next) 282*38fd1498Szrj __iter->_M_version = _M_version; 283*38fd1498Szrj 284*38fd1498Szrj for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 285*38fd1498Szrj __iter2 = __iter2->_M_next) 286*38fd1498Szrj __iter2->_M_version = _M_version; 287*38fd1498Szrj } 288*38fd1498Szrj 289*38fd1498Szrj void 290*38fd1498Szrj _Safe_sequence_base:: _M_swap(_Safe_sequence_base & __x)291*38fd1498Szrj _M_swap(_Safe_sequence_base& __x) noexcept 292*38fd1498Szrj { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } 293*38fd1498Szrj 294*38fd1498Szrj __gnu_cxx::__mutex& 295*38fd1498Szrj _Safe_sequence_base:: _M_get_mutex()296*38fd1498Szrj _M_get_mutex() throw () 297*38fd1498Szrj { return get_safe_base_mutex(this); } 298*38fd1498Szrj 299*38fd1498Szrj void 300*38fd1498Szrj _Safe_sequence_base:: _M_attach(_Safe_iterator_base * __it,bool __constant)301*38fd1498Szrj _M_attach(_Safe_iterator_base* __it, bool __constant) 302*38fd1498Szrj { 303*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 304*38fd1498Szrj _M_attach_single(__it, __constant); 305*38fd1498Szrj } 306*38fd1498Szrj 307*38fd1498Szrj void 308*38fd1498Szrj _Safe_sequence_base:: _M_attach_single(_Safe_iterator_base * __it,bool __constant)309*38fd1498Szrj _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw () 310*38fd1498Szrj { 311*38fd1498Szrj _Safe_iterator_base*& __its = 312*38fd1498Szrj __constant ? _M_const_iterators : _M_iterators; 313*38fd1498Szrj __it->_M_next = __its; 314*38fd1498Szrj if (__it->_M_next) 315*38fd1498Szrj __it->_M_next->_M_prior = __it; 316*38fd1498Szrj __its = __it; 317*38fd1498Szrj } 318*38fd1498Szrj 319*38fd1498Szrj void 320*38fd1498Szrj _Safe_sequence_base:: _M_detach(_Safe_iterator_base * __it)321*38fd1498Szrj _M_detach(_Safe_iterator_base* __it) 322*38fd1498Szrj { 323*38fd1498Szrj // Remove __it from this sequence's list 324*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 325*38fd1498Szrj _M_detach_single(__it); 326*38fd1498Szrj } 327*38fd1498Szrj 328*38fd1498Szrj void 329*38fd1498Szrj _Safe_sequence_base:: _M_detach_single(_Safe_iterator_base * __it)330*38fd1498Szrj _M_detach_single(_Safe_iterator_base* __it) throw () 331*38fd1498Szrj { 332*38fd1498Szrj // Remove __it from this sequence's list 333*38fd1498Szrj __it->_M_unlink(); 334*38fd1498Szrj if (_M_const_iterators == __it) 335*38fd1498Szrj _M_const_iterators = __it->_M_next; 336*38fd1498Szrj if (_M_iterators == __it) 337*38fd1498Szrj _M_iterators = __it->_M_next; 338*38fd1498Szrj } 339*38fd1498Szrj 340*38fd1498Szrj void 341*38fd1498Szrj _Safe_iterator_base:: _M_attach(_Safe_sequence_base * __seq,bool __constant)342*38fd1498Szrj _M_attach(_Safe_sequence_base* __seq, bool __constant) 343*38fd1498Szrj { 344*38fd1498Szrj _M_detach(); 345*38fd1498Szrj 346*38fd1498Szrj // Attach to the new sequence (if there is one) 347*38fd1498Szrj if (__seq) 348*38fd1498Szrj { 349*38fd1498Szrj _M_sequence = __seq; 350*38fd1498Szrj _M_version = _M_sequence->_M_version; 351*38fd1498Szrj _M_sequence->_M_attach(this, __constant); 352*38fd1498Szrj } 353*38fd1498Szrj } 354*38fd1498Szrj 355*38fd1498Szrj void 356*38fd1498Szrj _Safe_iterator_base:: _M_attach_single(_Safe_sequence_base * __seq,bool __constant)357*38fd1498Szrj _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw () 358*38fd1498Szrj { 359*38fd1498Szrj _M_detach_single(); 360*38fd1498Szrj 361*38fd1498Szrj // Attach to the new sequence (if there is one) 362*38fd1498Szrj if (__seq) 363*38fd1498Szrj { 364*38fd1498Szrj _M_sequence = __seq; 365*38fd1498Szrj _M_version = _M_sequence->_M_version; 366*38fd1498Szrj _M_sequence->_M_attach_single(this, __constant); 367*38fd1498Szrj } 368*38fd1498Szrj } 369*38fd1498Szrj 370*38fd1498Szrj void 371*38fd1498Szrj _Safe_iterator_base:: _M_detach()372*38fd1498Szrj _M_detach() 373*38fd1498Szrj { 374*38fd1498Szrj if (_M_sequence) 375*38fd1498Szrj _M_sequence->_M_detach(this); 376*38fd1498Szrj 377*38fd1498Szrj _M_reset(); 378*38fd1498Szrj } 379*38fd1498Szrj 380*38fd1498Szrj void 381*38fd1498Szrj _Safe_iterator_base:: _M_detach_single()382*38fd1498Szrj _M_detach_single() throw () 383*38fd1498Szrj { 384*38fd1498Szrj if (_M_sequence) 385*38fd1498Szrj _M_sequence->_M_detach_single(this); 386*38fd1498Szrj 387*38fd1498Szrj _M_reset(); 388*38fd1498Szrj } 389*38fd1498Szrj 390*38fd1498Szrj void 391*38fd1498Szrj _Safe_iterator_base:: _M_reset()392*38fd1498Szrj _M_reset() throw () 393*38fd1498Szrj { 394*38fd1498Szrj _M_sequence = 0; 395*38fd1498Szrj _M_version = 0; 396*38fd1498Szrj _M_prior = 0; 397*38fd1498Szrj _M_next = 0; 398*38fd1498Szrj } 399*38fd1498Szrj 400*38fd1498Szrj bool 401*38fd1498Szrj _Safe_iterator_base:: _M_singular() const402*38fd1498Szrj _M_singular() const throw () 403*38fd1498Szrj { return !_M_sequence || _M_version != _M_sequence->_M_version; } 404*38fd1498Szrj 405*38fd1498Szrj bool 406*38fd1498Szrj _Safe_iterator_base:: _M_can_compare(const _Safe_iterator_base & __x) const407*38fd1498Szrj _M_can_compare(const _Safe_iterator_base& __x) const throw () 408*38fd1498Szrj { 409*38fd1498Szrj return (!_M_singular() 410*38fd1498Szrj && !__x._M_singular() && _M_sequence == __x._M_sequence); 411*38fd1498Szrj } 412*38fd1498Szrj 413*38fd1498Szrj __gnu_cxx::__mutex& 414*38fd1498Szrj _Safe_iterator_base:: _M_get_mutex()415*38fd1498Szrj _M_get_mutex() throw () 416*38fd1498Szrj { return _M_sequence->_M_get_mutex(); } 417*38fd1498Szrj 418*38fd1498Szrj _Safe_unordered_container_base* 419*38fd1498Szrj _Safe_local_iterator_base:: _M_get_container() const420*38fd1498Szrj _M_get_container() const noexcept 421*38fd1498Szrj { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } 422*38fd1498Szrj 423*38fd1498Szrj void 424*38fd1498Szrj _Safe_local_iterator_base:: _M_attach(_Safe_sequence_base * __cont,bool __constant)425*38fd1498Szrj _M_attach(_Safe_sequence_base* __cont, bool __constant) 426*38fd1498Szrj { 427*38fd1498Szrj _M_detach(); 428*38fd1498Szrj 429*38fd1498Szrj // Attach to the new container (if there is one) 430*38fd1498Szrj if (__cont) 431*38fd1498Szrj { 432*38fd1498Szrj _M_sequence = __cont; 433*38fd1498Szrj _M_version = _M_sequence->_M_version; 434*38fd1498Szrj _M_get_container()->_M_attach_local(this, __constant); 435*38fd1498Szrj } 436*38fd1498Szrj } 437*38fd1498Szrj 438*38fd1498Szrj void 439*38fd1498Szrj _Safe_local_iterator_base:: _M_attach_single(_Safe_sequence_base * __cont,bool __constant)440*38fd1498Szrj _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw () 441*38fd1498Szrj { 442*38fd1498Szrj _M_detach_single(); 443*38fd1498Szrj 444*38fd1498Szrj // Attach to the new container (if there is one) 445*38fd1498Szrj if (__cont) 446*38fd1498Szrj { 447*38fd1498Szrj _M_sequence = __cont; 448*38fd1498Szrj _M_version = _M_sequence->_M_version; 449*38fd1498Szrj _M_get_container()->_M_attach_local_single(this, __constant); 450*38fd1498Szrj } 451*38fd1498Szrj } 452*38fd1498Szrj 453*38fd1498Szrj void 454*38fd1498Szrj _Safe_local_iterator_base:: _M_detach()455*38fd1498Szrj _M_detach() 456*38fd1498Szrj { 457*38fd1498Szrj if (_M_sequence) 458*38fd1498Szrj _M_get_container()->_M_detach_local(this); 459*38fd1498Szrj 460*38fd1498Szrj _M_reset(); 461*38fd1498Szrj } 462*38fd1498Szrj 463*38fd1498Szrj void 464*38fd1498Szrj _Safe_local_iterator_base:: _M_detach_single()465*38fd1498Szrj _M_detach_single() throw () 466*38fd1498Szrj { 467*38fd1498Szrj if (_M_sequence) 468*38fd1498Szrj _M_get_container()->_M_detach_local_single(this); 469*38fd1498Szrj 470*38fd1498Szrj _M_reset(); 471*38fd1498Szrj } 472*38fd1498Szrj 473*38fd1498Szrj void 474*38fd1498Szrj _Safe_unordered_container_base:: _M_detach_all()475*38fd1498Szrj _M_detach_all() 476*38fd1498Szrj { 477*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 478*38fd1498Szrj detach_all(_M_iterators); 479*38fd1498Szrj _M_iterators = 0; 480*38fd1498Szrj 481*38fd1498Szrj detach_all(_M_const_iterators); 482*38fd1498Szrj _M_const_iterators = 0; 483*38fd1498Szrj 484*38fd1498Szrj detach_all(_M_local_iterators); 485*38fd1498Szrj _M_local_iterators = 0; 486*38fd1498Szrj 487*38fd1498Szrj detach_all(_M_const_local_iterators); 488*38fd1498Szrj _M_const_local_iterators = 0; 489*38fd1498Szrj } 490*38fd1498Szrj 491*38fd1498Szrj void 492*38fd1498Szrj _Safe_unordered_container_base:: _M_swap(_Safe_unordered_container_base & __x)493*38fd1498Szrj _M_swap(_Safe_unordered_container_base& __x) noexcept 494*38fd1498Szrj { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } 495*38fd1498Szrj 496*38fd1498Szrj void 497*38fd1498Szrj _Safe_unordered_container_base:: _M_attach_local(_Safe_iterator_base * __it,bool __constant)498*38fd1498Szrj _M_attach_local(_Safe_iterator_base* __it, bool __constant) 499*38fd1498Szrj { 500*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 501*38fd1498Szrj _M_attach_local_single(__it, __constant); 502*38fd1498Szrj } 503*38fd1498Szrj 504*38fd1498Szrj void 505*38fd1498Szrj _Safe_unordered_container_base:: _M_attach_local_single(_Safe_iterator_base * __it,bool __constant)506*38fd1498Szrj _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw () 507*38fd1498Szrj { 508*38fd1498Szrj _Safe_iterator_base*& __its = 509*38fd1498Szrj __constant ? _M_const_local_iterators : _M_local_iterators; 510*38fd1498Szrj __it->_M_next = __its; 511*38fd1498Szrj if (__it->_M_next) 512*38fd1498Szrj __it->_M_next->_M_prior = __it; 513*38fd1498Szrj __its = __it; 514*38fd1498Szrj } 515*38fd1498Szrj 516*38fd1498Szrj void 517*38fd1498Szrj _Safe_unordered_container_base:: _M_detach_local(_Safe_iterator_base * __it)518*38fd1498Szrj _M_detach_local(_Safe_iterator_base* __it) 519*38fd1498Szrj { 520*38fd1498Szrj // Remove __it from this container's list 521*38fd1498Szrj __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 522*38fd1498Szrj _M_detach_local_single(__it); 523*38fd1498Szrj } 524*38fd1498Szrj 525*38fd1498Szrj void 526*38fd1498Szrj _Safe_unordered_container_base:: _M_detach_local_single(_Safe_iterator_base * __it)527*38fd1498Szrj _M_detach_local_single(_Safe_iterator_base* __it) throw () 528*38fd1498Szrj { 529*38fd1498Szrj // Remove __it from this container's list 530*38fd1498Szrj __it->_M_unlink(); 531*38fd1498Szrj if (_M_const_local_iterators == __it) 532*38fd1498Szrj _M_const_local_iterators = __it->_M_next; 533*38fd1498Szrj if (_M_local_iterators == __it) 534*38fd1498Szrj _M_local_iterators = __it->_M_next; 535*38fd1498Szrj } 536*38fd1498Szrj } 537*38fd1498Szrj 538*38fd1498Szrj namespace 539*38fd1498Szrj { 540*38fd1498Szrj using _Error_formatter = __gnu_debug::_Error_formatter; 541*38fd1498Szrj using _Parameter = __gnu_debug::_Error_formatter::_Parameter; 542*38fd1498Szrj 543*38fd1498Szrj void get_max_length(std::size_t & max_length)544*38fd1498Szrj get_max_length(std::size_t& max_length) 545*38fd1498Szrj { 546*38fd1498Szrj const char* nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH"); 547*38fd1498Szrj if (nptr) 548*38fd1498Szrj { 549*38fd1498Szrj char* endptr; 550*38fd1498Szrj const unsigned long ret = std::strtoul(nptr, &endptr, 0); 551*38fd1498Szrj if (*nptr != '\0' && *endptr == '\0') 552*38fd1498Szrj max_length = ret; 553*38fd1498Szrj } 554*38fd1498Szrj } 555*38fd1498Szrj 556*38fd1498Szrj struct PrintContext 557*38fd1498Szrj { PrintContext__anon9bf26f0f0411::PrintContext558*38fd1498Szrj PrintContext() 559*38fd1498Szrj : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 560*38fd1498Szrj { get_max_length(_M_max_length); } 561*38fd1498Szrj 562*38fd1498Szrj std::size_t _M_max_length; 563*38fd1498Szrj enum { _M_indent = 4 } ; 564*38fd1498Szrj std::size_t _M_column; 565*38fd1498Szrj bool _M_first_line; 566*38fd1498Szrj bool _M_wordwrap; 567*38fd1498Szrj }; 568*38fd1498Szrj 569*38fd1498Szrj template<size_t Length> 570*38fd1498Szrj void print_literal(PrintContext & ctx,const char (& word)[Length])571*38fd1498Szrj print_literal(PrintContext& ctx, const char(&word)[Length]) 572*38fd1498Szrj { print_word(ctx, word, Length - 1); } 573*38fd1498Szrj 574*38fd1498Szrj void print_word(PrintContext & ctx,const char * word,std::ptrdiff_t count=-1)575*38fd1498Szrj print_word(PrintContext& ctx, const char* word, 576*38fd1498Szrj std::ptrdiff_t count = -1) 577*38fd1498Szrj { 578*38fd1498Szrj size_t length = count >= 0 ? count : __builtin_strlen(word); 579*38fd1498Szrj if (length == 0) 580*38fd1498Szrj return; 581*38fd1498Szrj 582*38fd1498Szrj // Consider first '\n' at begining cause it impacts column. 583*38fd1498Szrj if (word[0] == '\n') 584*38fd1498Szrj { 585*38fd1498Szrj fprintf(stderr, "\n"); 586*38fd1498Szrj ctx._M_column = 1; 587*38fd1498Szrj ++word; 588*38fd1498Szrj --length; 589*38fd1498Szrj 590*38fd1498Szrj if (length == 0) 591*38fd1498Szrj return; 592*38fd1498Szrj } 593*38fd1498Szrj 594*38fd1498Szrj size_t visual_length 595*38fd1498Szrj = isspace(word[length - 1]) ? length - 1 : length; 596*38fd1498Szrj if (visual_length == 0 597*38fd1498Szrj || !ctx._M_wordwrap 598*38fd1498Szrj || (ctx._M_column + visual_length < ctx._M_max_length) 599*38fd1498Szrj || (visual_length >= ctx._M_max_length && ctx._M_column == 1)) 600*38fd1498Szrj { 601*38fd1498Szrj // If this isn't the first line, indent 602*38fd1498Szrj if (ctx._M_column == 1 && !ctx._M_first_line) 603*38fd1498Szrj { 604*38fd1498Szrj char spacing[ctx._M_indent + 1]; 605*38fd1498Szrj for (int i = 0; i < ctx._M_indent; ++i) 606*38fd1498Szrj spacing[i] = ' '; 607*38fd1498Szrj spacing[ctx._M_indent] = '\0'; 608*38fd1498Szrj fprintf(stderr, "%s", spacing); 609*38fd1498Szrj ctx._M_column += ctx._M_indent; 610*38fd1498Szrj } 611*38fd1498Szrj 612*38fd1498Szrj int written = fprintf(stderr, "%s", word); 613*38fd1498Szrj 614*38fd1498Szrj if (word[length - 1] == '\n') 615*38fd1498Szrj { 616*38fd1498Szrj ctx._M_first_line = false; 617*38fd1498Szrj ctx._M_column = 1; 618*38fd1498Szrj } 619*38fd1498Szrj else 620*38fd1498Szrj ctx._M_column += written; 621*38fd1498Szrj } 622*38fd1498Szrj else 623*38fd1498Szrj { 624*38fd1498Szrj print_literal(ctx, "\n"); 625*38fd1498Szrj print_word(ctx, word, count); 626*38fd1498Szrj } 627*38fd1498Szrj } 628*38fd1498Szrj 629*38fd1498Szrj template<size_t Length> 630*38fd1498Szrj void print_type(PrintContext & ctx,const type_info * info,const char (& unknown_name)[Length])631*38fd1498Szrj print_type(PrintContext& ctx, 632*38fd1498Szrj const type_info* info, 633*38fd1498Szrj const char(&unknown_name)[Length]) 634*38fd1498Szrj { 635*38fd1498Szrj if (!info) 636*38fd1498Szrj print_literal(ctx, unknown_name); 637*38fd1498Szrj else 638*38fd1498Szrj { 639*38fd1498Szrj int status; 640*38fd1498Szrj char* demangled_name = 641*38fd1498Szrj __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status); 642*38fd1498Szrj print_word(ctx, status == 0 ? demangled_name : info->name()); 643*38fd1498Szrj free(demangled_name); 644*38fd1498Szrj } 645*38fd1498Szrj } 646*38fd1498Szrj 647*38fd1498Szrj bool print_field(PrintContext & ctx,const char * name,const _Parameter::_Type & type)648*38fd1498Szrj print_field(PrintContext& ctx, 649*38fd1498Szrj const char* name, const _Parameter::_Type& type) 650*38fd1498Szrj { 651*38fd1498Szrj if (__builtin_strcmp(name, "name") == 0) 652*38fd1498Szrj { 653*38fd1498Szrj assert(type._M_name); 654*38fd1498Szrj print_word(ctx, type._M_name); 655*38fd1498Szrj } 656*38fd1498Szrj else if (__builtin_strcmp(name, "type") == 0) 657*38fd1498Szrj print_type(ctx, type._M_type, "<unknown type>"); 658*38fd1498Szrj else 659*38fd1498Szrj return false; 660*38fd1498Szrj 661*38fd1498Szrj return true; 662*38fd1498Szrj } 663*38fd1498Szrj 664*38fd1498Szrj bool print_field(PrintContext & ctx,const char * name,const _Parameter::_Instance & inst)665*38fd1498Szrj print_field(PrintContext& ctx, 666*38fd1498Szrj const char* name, const _Parameter::_Instance& inst) 667*38fd1498Szrj { 668*38fd1498Szrj const _Parameter::_Type& type = inst; 669*38fd1498Szrj if (print_field(ctx, name, type)) 670*38fd1498Szrj { } 671*38fd1498Szrj else if (__builtin_strcmp(name, "address") == 0) 672*38fd1498Szrj { 673*38fd1498Szrj char buf[64]; 674*38fd1498Szrj int ret = __builtin_sprintf(buf, "%p", inst._M_address); 675*38fd1498Szrj print_word(ctx, buf, ret); 676*38fd1498Szrj } 677*38fd1498Szrj else 678*38fd1498Szrj return false; 679*38fd1498Szrj 680*38fd1498Szrj return true; 681*38fd1498Szrj } 682*38fd1498Szrj 683*38fd1498Szrj void print_field(PrintContext & ctx,const _Parameter & param,const char * name)684*38fd1498Szrj print_field(PrintContext& ctx, const _Parameter& param, const char* name) 685*38fd1498Szrj { 686*38fd1498Szrj assert(param._M_kind != _Parameter::__unused_param); 687*38fd1498Szrj const int bufsize = 64; 688*38fd1498Szrj char buf[bufsize]; 689*38fd1498Szrj 690*38fd1498Szrj const auto& variant = param._M_variant; 691*38fd1498Szrj switch (param._M_kind) 692*38fd1498Szrj { 693*38fd1498Szrj case _Parameter::__iterator: 694*38fd1498Szrj { 695*38fd1498Szrj const auto& iterator = variant._M_iterator; 696*38fd1498Szrj if (print_field(ctx, name, iterator)) 697*38fd1498Szrj { } 698*38fd1498Szrj else if (__builtin_strcmp(name, "constness") == 0) 699*38fd1498Szrj { 700*38fd1498Szrj static const char* 701*38fd1498Szrj constness_names[_Error_formatter::__last_constness] = 702*38fd1498Szrj { 703*38fd1498Szrj "<unknown>", 704*38fd1498Szrj "constant", 705*38fd1498Szrj "mutable" 706*38fd1498Szrj }; 707*38fd1498Szrj print_word(ctx, constness_names[iterator._M_constness]); 708*38fd1498Szrj } 709*38fd1498Szrj else if (__builtin_strcmp(name, "state") == 0) 710*38fd1498Szrj { 711*38fd1498Szrj static const char* 712*38fd1498Szrj state_names[_Error_formatter::__last_state] = 713*38fd1498Szrj { 714*38fd1498Szrj "<unknown>", 715*38fd1498Szrj "singular", 716*38fd1498Szrj "dereferenceable (start-of-sequence)", 717*38fd1498Szrj "dereferenceable", 718*38fd1498Szrj "past-the-end", 719*38fd1498Szrj "before-begin" 720*38fd1498Szrj }; 721*38fd1498Szrj print_word(ctx, state_names[iterator._M_state]); 722*38fd1498Szrj } 723*38fd1498Szrj else if (__builtin_strcmp(name, "sequence") == 0) 724*38fd1498Szrj { 725*38fd1498Szrj assert(iterator._M_sequence); 726*38fd1498Szrj int written = __builtin_sprintf(buf, "%p", iterator._M_sequence); 727*38fd1498Szrj print_word(ctx, buf, written); 728*38fd1498Szrj } 729*38fd1498Szrj else if (__builtin_strcmp(name, "seq_type") == 0) 730*38fd1498Szrj print_type(ctx, iterator._M_seq_type, "<unknown seq_type>"); 731*38fd1498Szrj else 732*38fd1498Szrj assert(false); 733*38fd1498Szrj } 734*38fd1498Szrj break; 735*38fd1498Szrj 736*38fd1498Szrj case _Parameter::__sequence: 737*38fd1498Szrj if (!print_field(ctx, name, variant._M_sequence)) 738*38fd1498Szrj assert(false); 739*38fd1498Szrj break; 740*38fd1498Szrj 741*38fd1498Szrj case _Parameter::__integer: 742*38fd1498Szrj if (__builtin_strcmp(name, "name") == 0) 743*38fd1498Szrj { 744*38fd1498Szrj assert(variant._M_integer._M_name); 745*38fd1498Szrj print_word(ctx, variant._M_integer._M_name); 746*38fd1498Szrj } 747*38fd1498Szrj else 748*38fd1498Szrj assert(false); 749*38fd1498Szrj break; 750*38fd1498Szrj 751*38fd1498Szrj case _Parameter::__string: 752*38fd1498Szrj if (__builtin_strcmp(name, "name") == 0) 753*38fd1498Szrj { 754*38fd1498Szrj assert(variant._M_string._M_name); 755*38fd1498Szrj print_word(ctx, variant._M_string._M_name); 756*38fd1498Szrj } 757*38fd1498Szrj else 758*38fd1498Szrj assert(false); 759*38fd1498Szrj break; 760*38fd1498Szrj 761*38fd1498Szrj case _Parameter::__instance: 762*38fd1498Szrj if (!print_field(ctx, name, variant._M_instance)) 763*38fd1498Szrj assert(false); 764*38fd1498Szrj break; 765*38fd1498Szrj 766*38fd1498Szrj case _Parameter::__iterator_value_type: 767*38fd1498Szrj if (!print_field(ctx, name, variant._M_iterator_value_type)) 768*38fd1498Szrj assert(false); 769*38fd1498Szrj break; 770*38fd1498Szrj 771*38fd1498Szrj default: 772*38fd1498Szrj assert(false); 773*38fd1498Szrj break; 774*38fd1498Szrj } 775*38fd1498Szrj } 776*38fd1498Szrj 777*38fd1498Szrj void print_description(PrintContext & ctx,const _Parameter::_Type & type)778*38fd1498Szrj print_description(PrintContext& ctx, const _Parameter::_Type& type) 779*38fd1498Szrj { 780*38fd1498Szrj if (type._M_name) 781*38fd1498Szrj { 782*38fd1498Szrj print_literal(ctx, "\""); 783*38fd1498Szrj print_word(ctx, type._M_name); 784*38fd1498Szrj print_literal(ctx, "\""); 785*38fd1498Szrj } 786*38fd1498Szrj 787*38fd1498Szrj print_literal(ctx, " {\n"); 788*38fd1498Szrj 789*38fd1498Szrj if (type._M_type) 790*38fd1498Szrj { 791*38fd1498Szrj print_literal(ctx, " type = "); 792*38fd1498Szrj print_type(ctx, type._M_type, "<unknown type>"); 793*38fd1498Szrj print_literal(ctx, ";\n"); 794*38fd1498Szrj } 795*38fd1498Szrj } 796*38fd1498Szrj 797*38fd1498Szrj void print_description(PrintContext & ctx,const _Parameter::_Instance & inst)798*38fd1498Szrj print_description(PrintContext& ctx, const _Parameter::_Instance& inst) 799*38fd1498Szrj { 800*38fd1498Szrj const int bufsize = 64; 801*38fd1498Szrj char buf[bufsize]; 802*38fd1498Szrj 803*38fd1498Szrj if (inst._M_name) 804*38fd1498Szrj { 805*38fd1498Szrj print_literal(ctx, "\""); 806*38fd1498Szrj print_word(ctx, inst._M_name); 807*38fd1498Szrj print_literal(ctx, "\" "); 808*38fd1498Szrj } 809*38fd1498Szrj 810*38fd1498Szrj int written 811*38fd1498Szrj = __builtin_sprintf(buf, "@ 0x%p {\n", inst._M_address); 812*38fd1498Szrj print_word(ctx, buf, written); 813*38fd1498Szrj 814*38fd1498Szrj if (inst._M_type) 815*38fd1498Szrj { 816*38fd1498Szrj print_literal(ctx, " type = "); 817*38fd1498Szrj print_type(ctx, inst._M_type, "<unknown type>"); 818*38fd1498Szrj } 819*38fd1498Szrj } 820*38fd1498Szrj 821*38fd1498Szrj void print_description(PrintContext & ctx,const _Parameter & param)822*38fd1498Szrj print_description(PrintContext& ctx, const _Parameter& param) 823*38fd1498Szrj { 824*38fd1498Szrj const int bufsize = 128; 825*38fd1498Szrj char buf[bufsize]; 826*38fd1498Szrj 827*38fd1498Szrj const auto& variant = param._M_variant; 828*38fd1498Szrj switch (param._M_kind) 829*38fd1498Szrj { 830*38fd1498Szrj case _Parameter::__iterator: 831*38fd1498Szrj { 832*38fd1498Szrj const auto& ite = variant._M_iterator; 833*38fd1498Szrj 834*38fd1498Szrj print_literal(ctx, "iterator "); 835*38fd1498Szrj print_description(ctx, ite); 836*38fd1498Szrj 837*38fd1498Szrj if (ite._M_type) 838*38fd1498Szrj { 839*38fd1498Szrj if (ite._M_constness != _Error_formatter::__unknown_constness) 840*38fd1498Szrj { 841*38fd1498Szrj print_literal(ctx, " ("); 842*38fd1498Szrj print_field(ctx, param, "constness"); 843*38fd1498Szrj print_literal(ctx, " iterator)"); 844*38fd1498Szrj } 845*38fd1498Szrj 846*38fd1498Szrj print_literal(ctx, ";\n"); 847*38fd1498Szrj } 848*38fd1498Szrj 849*38fd1498Szrj if (ite._M_state != _Error_formatter::__unknown_state) 850*38fd1498Szrj { 851*38fd1498Szrj print_literal(ctx, " state = "); 852*38fd1498Szrj print_field(ctx, param, "state"); 853*38fd1498Szrj print_literal(ctx, ";\n"); 854*38fd1498Szrj } 855*38fd1498Szrj 856*38fd1498Szrj if (ite._M_sequence) 857*38fd1498Szrj { 858*38fd1498Szrj print_literal(ctx, " references sequence "); 859*38fd1498Szrj if (ite._M_seq_type) 860*38fd1498Szrj { 861*38fd1498Szrj print_literal(ctx, "with type '"); 862*38fd1498Szrj print_field(ctx, param, "seq_type"); 863*38fd1498Szrj print_literal(ctx, "' "); 864*38fd1498Szrj } 865*38fd1498Szrj 866*38fd1498Szrj int written 867*38fd1498Szrj = __builtin_sprintf(buf, "@ 0x%p\n", ite._M_sequence); 868*38fd1498Szrj print_word(ctx, buf, written); 869*38fd1498Szrj } 870*38fd1498Szrj 871*38fd1498Szrj print_literal(ctx, "}\n"); 872*38fd1498Szrj } 873*38fd1498Szrj break; 874*38fd1498Szrj 875*38fd1498Szrj case _Parameter::__sequence: 876*38fd1498Szrj print_literal(ctx, "sequence "); 877*38fd1498Szrj print_description(ctx, variant._M_sequence); 878*38fd1498Szrj 879*38fd1498Szrj if (variant._M_sequence._M_type) 880*38fd1498Szrj print_literal(ctx, ";\n"); 881*38fd1498Szrj 882*38fd1498Szrj print_literal(ctx, "}\n"); 883*38fd1498Szrj break; 884*38fd1498Szrj 885*38fd1498Szrj case _Parameter::__instance: 886*38fd1498Szrj print_literal(ctx, "instance "); 887*38fd1498Szrj print_description(ctx, variant._M_instance); 888*38fd1498Szrj 889*38fd1498Szrj if (variant._M_instance._M_type) 890*38fd1498Szrj print_literal(ctx, ";\n"); 891*38fd1498Szrj 892*38fd1498Szrj print_literal(ctx, "}\n"); 893*38fd1498Szrj break; 894*38fd1498Szrj 895*38fd1498Szrj case _Parameter::__iterator_value_type: 896*38fd1498Szrj print_literal(ctx, "iterator::value_type "); 897*38fd1498Szrj print_description(ctx, variant._M_iterator_value_type); 898*38fd1498Szrj print_literal(ctx, "}\n"); 899*38fd1498Szrj break; 900*38fd1498Szrj 901*38fd1498Szrj default: 902*38fd1498Szrj break; 903*38fd1498Szrj } 904*38fd1498Szrj } 905*38fd1498Szrj 906*38fd1498Szrj void print_string(PrintContext & ctx,const char * string,const _Parameter * parameters,std::size_t num_parameters)907*38fd1498Szrj print_string(PrintContext& ctx, const char* string, 908*38fd1498Szrj const _Parameter* parameters, std::size_t num_parameters) 909*38fd1498Szrj { 910*38fd1498Szrj const char* start = string; 911*38fd1498Szrj const int bufsize = 128; 912*38fd1498Szrj char buf[bufsize]; 913*38fd1498Szrj int bufindex = 0; 914*38fd1498Szrj 915*38fd1498Szrj while (*start) 916*38fd1498Szrj { 917*38fd1498Szrj if (isspace(*start)) 918*38fd1498Szrj { 919*38fd1498Szrj buf[bufindex++] = *start++; 920*38fd1498Szrj buf[bufindex] = '\0'; 921*38fd1498Szrj print_word(ctx, buf, bufindex); 922*38fd1498Szrj bufindex = 0; 923*38fd1498Szrj continue; 924*38fd1498Szrj } 925*38fd1498Szrj 926*38fd1498Szrj if (*start != '%') 927*38fd1498Szrj { 928*38fd1498Szrj // Normal char. 929*38fd1498Szrj buf[bufindex++] = *start++; 930*38fd1498Szrj continue; 931*38fd1498Szrj } 932*38fd1498Szrj 933*38fd1498Szrj if (*++start == '%') 934*38fd1498Szrj { 935*38fd1498Szrj // Escaped '%' 936*38fd1498Szrj buf[bufindex++] = *start++; 937*38fd1498Szrj continue; 938*38fd1498Szrj } 939*38fd1498Szrj 940*38fd1498Szrj // We are on a parameter property reference, we need to flush buffer 941*38fd1498Szrj // first. 942*38fd1498Szrj if (bufindex != 0) 943*38fd1498Szrj { 944*38fd1498Szrj buf[bufindex] = '\0'; 945*38fd1498Szrj print_word(ctx, buf, bufindex); 946*38fd1498Szrj bufindex = 0; 947*38fd1498Szrj } 948*38fd1498Szrj 949*38fd1498Szrj // Get the parameter number 950*38fd1498Szrj assert(*start >= '1' && *start <= '9'); 951*38fd1498Szrj size_t param_index = *start - '0' - 1; 952*38fd1498Szrj assert(param_index < num_parameters); 953*38fd1498Szrj const auto& param = parameters[param_index]; 954*38fd1498Szrj 955*38fd1498Szrj // '.' separates the parameter number from the field 956*38fd1498Szrj // name, if there is one. 957*38fd1498Szrj ++start; 958*38fd1498Szrj if (*start != '.') 959*38fd1498Szrj { 960*38fd1498Szrj assert(*start == ';'); 961*38fd1498Szrj ++start; 962*38fd1498Szrj if (param._M_kind == _Parameter::__integer) 963*38fd1498Szrj { 964*38fd1498Szrj int written 965*38fd1498Szrj = __builtin_sprintf(buf, "%ld", 966*38fd1498Szrj param._M_variant._M_integer._M_value); 967*38fd1498Szrj print_word(ctx, buf, written); 968*38fd1498Szrj } 969*38fd1498Szrj else if (param._M_kind == _Parameter::__string) 970*38fd1498Szrj print_string(ctx, param._M_variant._M_string._M_value, 971*38fd1498Szrj parameters, num_parameters); 972*38fd1498Szrj continue; 973*38fd1498Szrj } 974*38fd1498Szrj 975*38fd1498Szrj // Extract the field name we want 976*38fd1498Szrj const int max_field_len = 16; 977*38fd1498Szrj char field[max_field_len]; 978*38fd1498Szrj int field_idx = 0; 979*38fd1498Szrj ++start; 980*38fd1498Szrj while (*start != ';') 981*38fd1498Szrj { 982*38fd1498Szrj assert(*start); 983*38fd1498Szrj assert(field_idx < max_field_len - 1); 984*38fd1498Szrj field[field_idx++] = *start++; 985*38fd1498Szrj } 986*38fd1498Szrj ++start; 987*38fd1498Szrj field[field_idx] = '\0'; 988*38fd1498Szrj 989*38fd1498Szrj print_field(ctx, param, field); 990*38fd1498Szrj } 991*38fd1498Szrj 992*38fd1498Szrj // Might need to flush. 993*38fd1498Szrj if (bufindex) 994*38fd1498Szrj { 995*38fd1498Szrj buf[bufindex] = '\0'; 996*38fd1498Szrj print_word(ctx, buf, bufindex); 997*38fd1498Szrj } 998*38fd1498Szrj } 999*38fd1498Szrj } 1000*38fd1498Szrj 1001*38fd1498Szrj namespace __gnu_debug 1002*38fd1498Szrj { 1003*38fd1498Szrj _Error_formatter& _M_message(_Debug_msg_id __id) const1004*38fd1498Szrj _Error_formatter::_M_message(_Debug_msg_id __id) const throw () 1005*38fd1498Szrj { 1006*38fd1498Szrj return const_cast<_Error_formatter*>(this) 1007*38fd1498Szrj ->_M_message(_S_debug_messages[__id]); 1008*38fd1498Szrj } 1009*38fd1498Szrj 1010*38fd1498Szrj void _M_error() const1011*38fd1498Szrj _Error_formatter::_M_error() const 1012*38fd1498Szrj { 1013*38fd1498Szrj // Emit file & line number information 1014*38fd1498Szrj bool go_to_next_line = false; 1015*38fd1498Szrj PrintContext ctx; 1016*38fd1498Szrj if (_M_file) 1017*38fd1498Szrj { 1018*38fd1498Szrj print_word(ctx, _M_file); 1019*38fd1498Szrj print_literal(ctx, ":"); 1020*38fd1498Szrj go_to_next_line = true; 1021*38fd1498Szrj } 1022*38fd1498Szrj 1023*38fd1498Szrj if (_M_line > 0) 1024*38fd1498Szrj { 1025*38fd1498Szrj char buf[64]; 1026*38fd1498Szrj int written = __builtin_sprintf(buf, "%u:", _M_line); 1027*38fd1498Szrj print_word(ctx, buf, written); 1028*38fd1498Szrj go_to_next_line = true; 1029*38fd1498Szrj } 1030*38fd1498Szrj 1031*38fd1498Szrj if (go_to_next_line) 1032*38fd1498Szrj print_literal(ctx, "\n"); 1033*38fd1498Szrj 1034*38fd1498Szrj if (ctx._M_max_length) 1035*38fd1498Szrj ctx._M_wordwrap = true; 1036*38fd1498Szrj 1037*38fd1498Szrj print_literal(ctx, "Error: "); 1038*38fd1498Szrj 1039*38fd1498Szrj // Print the error message 1040*38fd1498Szrj assert(_M_text); 1041*38fd1498Szrj print_string(ctx, _M_text, _M_parameters, _M_num_parameters); 1042*38fd1498Szrj print_literal(ctx, ".\n"); 1043*38fd1498Szrj 1044*38fd1498Szrj // Emit descriptions of the objects involved in the operation 1045*38fd1498Szrj ctx._M_first_line = true; 1046*38fd1498Szrj ctx._M_wordwrap = false; 1047*38fd1498Szrj bool has_header = false; 1048*38fd1498Szrj for (unsigned int i = 0; i < _M_num_parameters; ++i) 1049*38fd1498Szrj { 1050*38fd1498Szrj switch (_M_parameters[i]._M_kind) 1051*38fd1498Szrj { 1052*38fd1498Szrj case _Parameter::__iterator: 1053*38fd1498Szrj case _Parameter::__sequence: 1054*38fd1498Szrj case _Parameter::__instance: 1055*38fd1498Szrj case _Parameter::__iterator_value_type: 1056*38fd1498Szrj if (!has_header) 1057*38fd1498Szrj { 1058*38fd1498Szrj print_literal(ctx, "\nObjects involved in the operation:\n"); 1059*38fd1498Szrj has_header = true; 1060*38fd1498Szrj } 1061*38fd1498Szrj print_description(ctx, _M_parameters[i]); 1062*38fd1498Szrj break; 1063*38fd1498Szrj 1064*38fd1498Szrj default: 1065*38fd1498Szrj break; 1066*38fd1498Szrj } 1067*38fd1498Szrj } 1068*38fd1498Szrj 1069*38fd1498Szrj abort(); 1070*38fd1498Szrj } 1071*38fd1498Szrj 1072*38fd1498Szrj #if !_GLIBCXX_INLINE_VERSION 1073*38fd1498Szrj // Deprecated methods kept for backward compatibility. 1074*38fd1498Szrj void _M_print_field(const _Error_formatter *,const char *) const1075*38fd1498Szrj _Error_formatter::_Parameter::_M_print_field( 1076*38fd1498Szrj const _Error_formatter*, const char*) const 1077*38fd1498Szrj { } 1078*38fd1498Szrj 1079*38fd1498Szrj void _M_print_description(const _Error_formatter *) const1080*38fd1498Szrj _Error_formatter::_Parameter::_M_print_description(const _Error_formatter*) const 1081*38fd1498Szrj { } 1082*38fd1498Szrj 1083*38fd1498Szrj template<typename _Tp> 1084*38fd1498Szrj void _M_format_word(char *,int,const char *,_Tp) const1085*38fd1498Szrj _Error_formatter::_M_format_word(char*, int, const char*, _Tp) 1086*38fd1498Szrj const throw () 1087*38fd1498Szrj { } 1088*38fd1498Szrj 1089*38fd1498Szrj void _M_print_word(const char *) const1090*38fd1498Szrj _Error_formatter::_M_print_word(const char*) const 1091*38fd1498Szrj { } 1092*38fd1498Szrj 1093*38fd1498Szrj void _M_print_string(const char *) const1094*38fd1498Szrj _Error_formatter::_M_print_string(const char*) const 1095*38fd1498Szrj { } 1096*38fd1498Szrj 1097*38fd1498Szrj void _M_get_max_length() const1098*38fd1498Szrj _Error_formatter::_M_get_max_length() const throw () 1099*38fd1498Szrj { } 1100*38fd1498Szrj 1101*38fd1498Szrj // Instantiations. 1102*38fd1498Szrj template 1103*38fd1498Szrj void 1104*38fd1498Szrj _Error_formatter::_M_format_word(char*, int, const char*, 1105*38fd1498Szrj const void*) const; 1106*38fd1498Szrj 1107*38fd1498Szrj template 1108*38fd1498Szrj void 1109*38fd1498Szrj _Error_formatter::_M_format_word(char*, int, const char*, long) const; 1110*38fd1498Szrj 1111*38fd1498Szrj template 1112*38fd1498Szrj void 1113*38fd1498Szrj _Error_formatter::_M_format_word(char*, int, const char*, 1114*38fd1498Szrj std::size_t) const; 1115*38fd1498Szrj 1116*38fd1498Szrj template 1117*38fd1498Szrj void 1118*38fd1498Szrj _Error_formatter::_M_format_word(char*, int, const char*, 1119*38fd1498Szrj const char*) const; 1120*38fd1498Szrj #endif 1121*38fd1498Szrj 1122*38fd1498Szrj } // namespace __gnu_debug 1123