stacktrace 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. // <stacktrace> -*- C++ -*-
  2. // Copyright The GNU Toolchain Authors.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3.
  8. // This library is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. // Under Section 7 of GPL version 3, you are granted additional
  13. // permissions described in the GCC Runtime Library Exception, version
  14. // 3.1, as published by the Free Software Foundation.
  15. // You should have received a copy of the GNU General Public License and
  16. // a copy of the GCC Runtime Library Exception along with this program;
  17. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. // <http://www.gnu.org/licenses/>.
  19. #ifndef _GLIBCXX_STACKTRACE
  20. #define _GLIBCXX_STACKTRACE 1
  21. #pragma GCC system_header
  22. #include <bits/c++config.h>
  23. #if __cplusplus > 202002L && _GLIBCXX_HAVE_STACKTRACE
  24. #include <compare>
  25. #include <new>
  26. #include <string>
  27. #include <sstream>
  28. #include <bits/stl_algobase.h>
  29. #include <bits/stl_algo.h>
  30. #include <bits/stl_iterator.h>
  31. #include <bits/stl_uninitialized.h>
  32. #include <ext/numeric_traits.h>
  33. struct __glibcxx_backtrace_state;
  34. struct __glibcxx_backtrace_simple_data;
  35. extern "C"
  36. {
  37. __glibcxx_backtrace_state*
  38. __glibcxx_backtrace_create_state(const char*, int,
  39. void(*)(void*, const char*, int),
  40. void*);
  41. int
  42. __glibcxx_backtrace_simple(__glibcxx_backtrace_state*, int,
  43. int (*) (void*, uintptr_t),
  44. void(*)(void*, const char*, int),
  45. void*);
  46. int
  47. __glibcxx_backtrace_pcinfo(__glibcxx_backtrace_state*, uintptr_t,
  48. int (*)(void*, uintptr_t,
  49. const char*, int, const char*),
  50. void(*)(void*, const char*, int),
  51. void*);
  52. int
  53. __glibcxx_backtrace_syminfo(__glibcxx_backtrace_state*, uintptr_t addr,
  54. void (*) (void*, uintptr_t, const char*,
  55. uintptr_t, uintptr_t),
  56. void(*)(void*, const char*, int),
  57. void*);
  58. }
  59. namespace __cxxabiv1
  60. {
  61. extern "C" char*
  62. __cxa_demangle(const char* __mangled_name, char* __output_buffer,
  63. size_t* __length, int* __status);
  64. }
  65. namespace std _GLIBCXX_VISIBILITY(default)
  66. {
  67. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  68. #define __cpp_lib_stacktrace 202011L
  69. // [stacktrace.entry], class stacktrace_entry
  70. class stacktrace_entry
  71. {
  72. using uint_least32_t = __UINT_LEAST32_TYPE__;
  73. using uintptr_t = __UINTPTR_TYPE__;
  74. public:
  75. using native_handle_type = uintptr_t;
  76. // [stacktrace.entry.ctor], constructors
  77. constexpr
  78. stacktrace_entry() noexcept = default;
  79. constexpr
  80. stacktrace_entry(const stacktrace_entry& __other) noexcept = default;
  81. constexpr stacktrace_entry&
  82. operator=(const stacktrace_entry& __other) noexcept = default;
  83. ~stacktrace_entry() = default;
  84. // [stacktrace.entry.obs], observers
  85. constexpr native_handle_type
  86. native_handle() const noexcept { return _M_pc; }
  87. constexpr explicit operator bool() const noexcept { return _M_pc != -1; }
  88. // [stacktrace.entry.query], query
  89. string
  90. description() const
  91. {
  92. string __s;
  93. _M_get_info(&__s, nullptr, nullptr);
  94. return __s;
  95. }
  96. string
  97. source_file() const
  98. {
  99. string __s;
  100. _M_get_info(nullptr, &__s, nullptr);
  101. return __s;
  102. }
  103. uint_least32_t
  104. source_line() const
  105. {
  106. int __line = 0;
  107. _M_get_info(nullptr, nullptr, &__line);
  108. return __line;
  109. }
  110. // [stacktrace.entry.cmp], comparison
  111. friend constexpr bool
  112. operator==(const stacktrace_entry& __x,
  113. const stacktrace_entry& __y) noexcept
  114. { return __x._M_pc == __y._M_pc; }
  115. friend constexpr strong_ordering
  116. operator<=>(const stacktrace_entry& __x,
  117. const stacktrace_entry& __y) noexcept
  118. { return __x._M_pc <=> __y._M_pc; }
  119. private:
  120. native_handle_type _M_pc = -1;
  121. template<typename _Allocator> friend class basic_stacktrace;
  122. static __glibcxx_backtrace_state*
  123. _S_init()
  124. {
  125. static __glibcxx_backtrace_state* __state
  126. = __glibcxx_backtrace_create_state(nullptr, 1, nullptr, nullptr);
  127. return __state;
  128. }
  129. template<typename _CharT, typename _Traits>
  130. friend basic_ostream<_CharT, _Traits>&
  131. operator<<(basic_ostream<_CharT, _Traits>&, const stacktrace_entry&);
  132. bool
  133. _M_get_info(string* __desc, string* __file, int* __line) const
  134. {
  135. if (!*this)
  136. return false;
  137. struct _Data
  138. {
  139. string* _M_desc;
  140. string* _M_file;
  141. int* _M_line;
  142. } __data = { __desc, __file, __line };
  143. auto __cb = [](void* __data, uintptr_t, const char* __filename,
  144. int __lineno, const char* __function) -> int {
  145. auto& __d = *static_cast<_Data*>(__data);
  146. if (__function && __d._M_desc)
  147. *__d._M_desc = _S_demangle(__function);
  148. if (__filename && __d._M_file)
  149. *__d._M_file = __filename;
  150. if (__d._M_line)
  151. *__d._M_line = __lineno;
  152. return __function != nullptr;
  153. };
  154. const auto __state = _S_init();
  155. if (::__glibcxx_backtrace_pcinfo(__state, _M_pc, +__cb, nullptr, &__data))
  156. return true;
  157. if (__desc && __desc->empty())
  158. {
  159. auto __cb2 = [](void* __data, uintptr_t, const char* __symname,
  160. uintptr_t, uintptr_t) {
  161. if (__symname)
  162. *static_cast<_Data*>(__data)->_M_desc = _S_demangle(__symname);
  163. };
  164. if (::__glibcxx_backtrace_syminfo(__state, _M_pc, +__cb2, nullptr,
  165. &__data))
  166. return true;
  167. }
  168. return false;
  169. }
  170. static string
  171. _S_demangle(const char* __name)
  172. {
  173. string __s;
  174. int __status;
  175. char* __str = __cxxabiv1::__cxa_demangle(__name, nullptr, nullptr,
  176. &__status);
  177. if (__status == 0)
  178. __s = __str;
  179. __builtin_free(__str);
  180. return __s;
  181. }
  182. };
  183. // [stacktrace.basic], class template basic_stacktrace
  184. template<typename _Allocator>
  185. class basic_stacktrace
  186. {
  187. using _AllocTraits = allocator_traits<_Allocator>;
  188. public:
  189. using value_type = stacktrace_entry;
  190. using const_reference = const value_type&;
  191. using reference = value_type&;
  192. using const_iterator
  193. = __gnu_cxx::__normal_iterator<value_type*, basic_stacktrace>;
  194. using iterator = const_iterator;
  195. using reverse_iterator = std::reverse_iterator<iterator>;
  196. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  197. using difference_type = ptrdiff_t;
  198. using size_type = unsigned short;
  199. using allocator_type = _Allocator;
  200. // [stacktrace.basic.ctor], creation and assignment
  201. [[__gnu__::__noinline__]]
  202. static basic_stacktrace
  203. current(const allocator_type& __alloc = allocator_type()) noexcept
  204. {
  205. basic_stacktrace __ret(__alloc);
  206. if (auto __cb = __ret._M_prepare()) [[likely]]
  207. {
  208. auto __state = stacktrace_entry::_S_init();
  209. if (__glibcxx_backtrace_simple(__state, 1, __cb, nullptr,
  210. std::__addressof(__ret)))
  211. __ret._M_clear();
  212. }
  213. return __ret;
  214. }
  215. [[__gnu__::__noinline__]]
  216. static basic_stacktrace
  217. current(size_type __skip,
  218. const allocator_type& __alloc = allocator_type()) noexcept
  219. {
  220. basic_stacktrace __ret(__alloc);
  221. if (__skip >= __INT_MAX__) [[unlikely]]
  222. return __ret;
  223. if (auto __cb = __ret._M_prepare()) [[likely]]
  224. {
  225. auto __state = stacktrace_entry::_S_init();
  226. if (__glibcxx_backtrace_simple(__state, __skip + 1, __cb, nullptr,
  227. std::__addressof(__ret)))
  228. __ret._M_clear();
  229. }
  230. return __ret;
  231. }
  232. [[__gnu__::__noinline__]]
  233. static basic_stacktrace
  234. current(size_type __skip, size_type __max_depth,
  235. const allocator_type& __alloc = allocator_type()) noexcept
  236. {
  237. __glibcxx_assert(__skip <= (size_type(-1) - __max_depth));
  238. basic_stacktrace __ret(__alloc);
  239. if (__max_depth == 0) [[unlikely]]
  240. return __ret;
  241. if (__skip >= __INT_MAX__) [[unlikely]]
  242. return __ret;
  243. if (auto __cb = __ret._M_prepare(__max_depth)) [[likely]]
  244. {
  245. auto __state = stacktrace_entry::_S_init();
  246. int __err = __glibcxx_backtrace_simple(__state, __skip + 1, __cb,
  247. nullptr,
  248. std::__addressof(__ret));
  249. if (__err < 0)
  250. __ret._M_clear();
  251. else if (__ret.size() > __max_depth)
  252. {
  253. __ret._M_impl._M_resize(__max_depth, __ret._M_alloc);
  254. if (__ret._M_impl._M_capacity / 2 >= __max_depth)
  255. {
  256. // shrink to fit
  257. _Impl __tmp = __ret._M_impl._M_clone(__ret._M_alloc);
  258. if (__tmp._M_capacity)
  259. {
  260. __ret._M_clear();
  261. __ret._M_impl = __tmp;
  262. }
  263. }
  264. }
  265. }
  266. return __ret;
  267. }
  268. basic_stacktrace()
  269. noexcept(is_nothrow_default_constructible_v<allocator_type>)
  270. { }
  271. explicit
  272. basic_stacktrace(const allocator_type& __alloc) noexcept
  273. : _M_alloc(__alloc)
  274. { }
  275. basic_stacktrace(const basic_stacktrace& __other) noexcept
  276. : basic_stacktrace(__other,
  277. _AllocTraits::select_on_container_copy_construction(__other._M_alloc))
  278. { }
  279. basic_stacktrace(basic_stacktrace&& __other) noexcept
  280. : _M_alloc(std::move(__other._M_alloc)),
  281. _M_impl(std::__exchange(__other._M_impl, {}))
  282. { }
  283. basic_stacktrace(const basic_stacktrace& __other,
  284. const allocator_type& __alloc) noexcept
  285. : _M_alloc(__alloc)
  286. {
  287. if (const auto __s = __other._M_impl._M_size)
  288. _M_impl = __other._M_impl._M_clone(_M_alloc);
  289. }
  290. basic_stacktrace(basic_stacktrace&& __other,
  291. const allocator_type& __alloc) noexcept
  292. : _M_alloc(__alloc)
  293. {
  294. if constexpr (_Allocator::is_always_equal::value)
  295. _M_impl = std::__exchange(__other._M_impl, {});
  296. else if (_M_alloc == __other._M_alloc)
  297. _M_impl = std::__exchange(__other._M_impl, {});
  298. else if (const auto __s = __other._M_impl._M_size)
  299. _M_impl = __other._M_impl._M_clone(_M_alloc);
  300. }
  301. basic_stacktrace&
  302. operator=(const basic_stacktrace& __other) noexcept
  303. {
  304. if (std::__addressof(__other) == this)
  305. return *this;
  306. constexpr bool __pocca
  307. = _AllocTraits::propagate_on_container_copy_assignment::value;
  308. constexpr bool __always_eq = _AllocTraits::is_always_equal::value;
  309. const auto __s = __other.size();
  310. if constexpr (!__always_eq && __pocca)
  311. {
  312. if (_M_alloc != __other._M_alloc)
  313. {
  314. // Cannot keep the same storage, so deallocate it now.
  315. _M_clear();
  316. }
  317. }
  318. if (_M_impl._M_capacity < __s)
  319. {
  320. // Need to allocate new storage.
  321. _M_clear();
  322. if constexpr (__pocca)
  323. _M_alloc = __other._M_alloc;
  324. _M_impl = __other._M_impl._M_clone(_M_alloc);
  325. }
  326. else
  327. {
  328. // Current storage is large enough.
  329. _M_impl._M_resize(0, _M_alloc);
  330. _M_impl._M_assign(__other._M_impl, _M_alloc);
  331. if constexpr (__pocca)
  332. _M_alloc = __other._M_alloc;
  333. }
  334. return *this;
  335. }
  336. basic_stacktrace&
  337. operator=(basic_stacktrace&& __other) noexcept
  338. {
  339. if (std::__addressof(__other) == this)
  340. return *this;
  341. constexpr bool __pocma
  342. = _AllocTraits::propagate_on_container_move_assignment::value;
  343. if constexpr (_AllocTraits::is_always_equal::value)
  344. std::swap(_M_impl, __other._M_impl);
  345. else if (_M_alloc == __other._M_alloc)
  346. std::swap(_M_impl, __other._M_impl);
  347. else if constexpr (__pocma)
  348. {
  349. // Free current storage and take ownership of __other's storage.
  350. _M_clear();
  351. _M_impl = std::__exchange(__other._M_impl, {});
  352. }
  353. else // Allocators are unequal and don't propagate.
  354. {
  355. const size_type __s = __other.size();
  356. if (_M_impl._M_capacity < __s)
  357. {
  358. // Need to allocate new storage.
  359. _M_clear();
  360. _M_impl = __other._M_impl._M_clone(_M_alloc);
  361. }
  362. else
  363. {
  364. // Current storage is large enough.
  365. _M_impl._M_resize(0, _M_alloc);
  366. _M_impl._M_assign(__other._M_impl, _M_alloc);
  367. }
  368. }
  369. if constexpr (__pocma)
  370. _M_alloc = std::move(__other._M_alloc);
  371. return *this;
  372. }
  373. constexpr ~basic_stacktrace()
  374. {
  375. _M_clear();
  376. }
  377. // [stacktrace.basic.obs], observers
  378. allocator_type get_allocator() const noexcept { return _M_alloc; }
  379. const_iterator
  380. begin() const noexcept
  381. { return const_iterator{_M_impl._M_frames}; }
  382. const_iterator
  383. end() const noexcept
  384. { return begin() + size(); }
  385. const_reverse_iterator
  386. rbegin() const noexcept
  387. { return std::make_reverse_iterator(end()); }
  388. const_reverse_iterator
  389. rend() const noexcept
  390. { return std::make_reverse_iterator(begin()); }
  391. const_iterator cbegin() const noexcept { return begin(); }
  392. const_iterator cend() const noexcept { return end(); }
  393. const_reverse_iterator crbegin() const noexcept { return rbegin(); };
  394. const_reverse_iterator crend() const noexcept { return rend(); };
  395. [[nodiscard]] bool empty() const noexcept { return size() == 0; }
  396. size_type size() const noexcept { return _M_impl._M_size; }
  397. size_type
  398. max_size() const noexcept
  399. { return _Impl::_S_max_size(_M_impl._M_alloc); }
  400. const_reference
  401. operator[](size_type __n) const noexcept
  402. {
  403. __glibcxx_assert(__n < size());
  404. return begin()[__n];
  405. }
  406. const_reference
  407. at(size_type __n) const
  408. {
  409. if (__n >= size())
  410. __throw_out_of_range("basic_stack_trace::at: bad frame number");
  411. return begin()[__n];
  412. }
  413. // [stacktrace.basic.cmp], comparisons
  414. template<typename _Allocator2>
  415. friend bool
  416. operator==(const basic_stacktrace& __x,
  417. const basic_stacktrace<_Allocator2>& __y) noexcept
  418. { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
  419. template<typename _Allocator2>
  420. friend strong_ordering
  421. operator<=>(const basic_stacktrace& __x,
  422. const basic_stacktrace<_Allocator2>& __y) noexcept
  423. {
  424. if (auto __s = __x.size() <=> __y.size(); __s != 0)
  425. return __s;
  426. return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
  427. __y.begin(), __y.end());
  428. }
  429. // [stacktrace.basic.mod], modifiers
  430. void
  431. swap(basic_stacktrace& __other) noexcept
  432. {
  433. std::swap(_M_impl, __other._M_impl);
  434. if constexpr (_AllocTraits::propagate_on_container_swap::value)
  435. std::swap(_M_alloc, __other._M_alloc);
  436. else if constexpr (!_AllocTraits::is_always_equal::value)
  437. {
  438. __glibcxx_assert(_M_alloc == __other._M_alloc);
  439. }
  440. }
  441. private:
  442. bool
  443. _M_push_back(const value_type& __x) noexcept
  444. {
  445. return _M_impl._M_push_back(_M_alloc, __x);
  446. }
  447. void
  448. _M_clear() noexcept
  449. {
  450. _M_impl._M_resize(0, _M_alloc);
  451. _M_impl._M_deallocate(_M_alloc);
  452. }
  453. // Precondition: __max_depth != 0
  454. auto
  455. _M_prepare(size_type __max_depth = -1) noexcept
  456. -> int (*) (void*, uintptr_t)
  457. {
  458. auto __cb = +[](void* __data, uintptr_t __pc) {
  459. auto& __s = *static_cast<basic_stacktrace*>(__data);
  460. stacktrace_entry __f;
  461. __f._M_pc = __pc;
  462. if (__s._M_push_back(__f)) [[likely]]
  463. return 0; // continue tracing
  464. return -1; // stop tracing due to error
  465. };
  466. if (__max_depth > 128)
  467. __max_depth = 64; // soft limit, _M_push_back will reallocate
  468. else
  469. __cb = [](void* __data, uintptr_t __pc) {
  470. auto& __s = *static_cast<basic_stacktrace*>(__data);
  471. stacktrace_entry __f;
  472. __f._M_pc = __pc;
  473. if (__s.size() == __s._M_impl._M_capacity) [[unlikely]]
  474. return 1; // stop tracing due to reaching max depth
  475. if (__s._M_push_back(__f)) [[likely]]
  476. return 0; // continue tracing
  477. return -1; // stop tracing due to error
  478. };
  479. if (_M_impl._M_allocate(_M_alloc, __max_depth)) [[likely]]
  480. return __cb;
  481. return nullptr;
  482. }
  483. struct _Impl
  484. {
  485. using pointer = typename _AllocTraits::pointer;
  486. pointer _M_frames = nullptr;
  487. size_type _M_size = 0;
  488. size_type _M_capacity = 0;
  489. static size_type
  490. _S_max_size(const allocator_type& __alloc) noexcept
  491. {
  492. const size_t __size_max = __gnu_cxx::__int_traits<size_type>::__max;
  493. const size_t __alloc_max = _AllocTraits::max_size(__alloc);
  494. return std::min(__size_max, __alloc_max);
  495. }
  496. #if __has_builtin(__builtin_operator_new) >= 201802L
  497. # define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
  498. # define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
  499. #else
  500. # define _GLIBCXX_OPERATOR_NEW ::operator new
  501. # define _GLIBCXX_OPERATOR_DELETE ::operator delete
  502. #endif
  503. // Precondition: _M_frames == nullptr && __n != 0
  504. pointer
  505. _M_allocate(allocator_type& __alloc, size_type __n) noexcept
  506. {
  507. if (__n <= _S_max_size(__alloc)) [[likely]]
  508. {
  509. if constexpr (is_same_v<allocator_type, allocator<value_type>>)
  510. {
  511. __n *= sizeof(value_type);
  512. void* const __p = _GLIBCXX_OPERATOR_NEW (__n, nothrow_t{});
  513. if (__p == nullptr) [[unlikely]]
  514. return nullptr;
  515. _M_frames = static_cast<pointer>(__p);
  516. }
  517. else
  518. {
  519. __try
  520. {
  521. _M_frames = __alloc.allocate(__n);
  522. }
  523. __catch (const std::bad_alloc&)
  524. {
  525. return nullptr;
  526. }
  527. }
  528. _M_capacity = __n;
  529. return _M_frames;
  530. }
  531. return nullptr;
  532. }
  533. void
  534. _M_deallocate(allocator_type& __alloc) noexcept
  535. {
  536. if (_M_capacity)
  537. {
  538. if constexpr (is_same_v<allocator_type, allocator<value_type>>)
  539. _GLIBCXX_OPERATOR_DELETE (static_cast<void*>(_M_frames),
  540. _M_capacity * sizeof(value_type));
  541. else
  542. __alloc.deallocate(_M_frames, _M_capacity);
  543. _M_frames = nullptr;
  544. _M_capacity = 0;
  545. }
  546. }
  547. #undef _GLIBCXX_OPERATOR_DELETE
  548. #undef _GLIBCXX_OPERATOR_NEW
  549. // Precondition: __n <= _M_size
  550. void
  551. _M_resize(size_type __n, allocator_type& __alloc) noexcept
  552. {
  553. for (size_type __i = __n; __i < _M_size; ++__i)
  554. _AllocTraits::destroy(__alloc, &_M_frames[__i]);
  555. _M_size = __n;
  556. }
  557. bool
  558. _M_push_back(allocator_type& __alloc,
  559. const stacktrace_entry& __f) noexcept
  560. {
  561. if (_M_size == _M_capacity) [[unlikely]]
  562. {
  563. _Impl __tmp = _M_xclone(_M_capacity ? _M_capacity : 8, __alloc);
  564. if (!__tmp._M_capacity) [[unlikely]]
  565. return false;
  566. _M_resize(0, __alloc);
  567. _M_deallocate(__alloc);
  568. *this = __tmp;
  569. }
  570. stacktrace_entry* __addr = std::to_address(_M_frames + _M_size++);
  571. _AllocTraits::construct(__alloc, __addr, __f);
  572. return true;
  573. }
  574. // Precondition: _M_size != 0
  575. _Impl
  576. _M_clone(allocator_type& __alloc) const noexcept
  577. {
  578. return _M_xclone(_M_size, __alloc);
  579. }
  580. // Precondition: _M_size != 0 || __extra != 0
  581. _Impl
  582. _M_xclone(size_type __extra, allocator_type& __alloc) const noexcept
  583. {
  584. _Impl __i;
  585. if (__i._M_allocate(__alloc, _M_size + __extra)) [[likely]]
  586. __i._M_assign(*this, __alloc);
  587. return __i;
  588. }
  589. // Precondition: _M_capacity >= __other._M_size
  590. void
  591. _M_assign(const _Impl& __other, allocator_type& __alloc) noexcept
  592. {
  593. std::__uninitialized_copy_a(__other._M_frames,
  594. __other._M_frames + __other._M_size,
  595. _M_frames, __alloc);
  596. _M_size = __other._M_size;
  597. }
  598. };
  599. [[no_unique_address]] allocator_type _M_alloc{};
  600. _Impl _M_impl{};
  601. };
  602. // basic_stacktrace typedef names
  603. using stacktrace = basic_stacktrace<allocator<stacktrace_entry>>;
  604. // [stacktrace.basic.nonmem], non-member functions
  605. template<typename _Allocator>
  606. inline void
  607. swap(basic_stacktrace<_Allocator>& __a, basic_stacktrace<_Allocator>& __b)
  608. noexcept(noexcept(__a.swap(__b)))
  609. { __a.swap(__b); }
  610. template<typename _CharT, typename _Traits>
  611. inline basic_ostream<_CharT, _Traits>&
  612. operator<<(basic_ostream<_CharT, _Traits>& __os,
  613. const stacktrace_entry& __f)
  614. {
  615. string __desc, __file;
  616. int __line;
  617. if (__f._M_get_info(&__desc, &__file, &__line))
  618. {
  619. __os.width(4);
  620. __os << __desc << " at " << __file << ':' << __line;
  621. }
  622. return __os;
  623. }
  624. template<typename _CharT, typename _Traits, typename _Allocator>
  625. inline basic_ostream<_CharT, _Traits>&
  626. operator<<(basic_ostream<_CharT, _Traits>& __os,
  627. const basic_stacktrace<_Allocator>& __st)
  628. {
  629. for (stacktrace::size_type __i = 0; __i < __st.size(); ++__i)
  630. {
  631. __os.width(4);
  632. __os << __i << "# " << __st[__i] << '\n';
  633. }
  634. return __os;
  635. }
  636. inline string
  637. to_string(const stacktrace_entry& __f)
  638. {
  639. std::ostringstream __os;
  640. __os << __f;
  641. return std::move(__os).str();
  642. }
  643. template<typename _Allocator>
  644. string
  645. to_string(const basic_stacktrace<_Allocator>& __st)
  646. {
  647. std::ostringstream __os;
  648. __os << __st;
  649. return std::move(__os).str();
  650. }
  651. namespace pmr
  652. {
  653. template<typename _Tp> class polymorphic_allocator;
  654. using stacktrace
  655. = basic_stacktrace<polymorphic_allocator<stacktrace_entry>>;
  656. }
  657. // [stacktrace.basic.hash], hash support
  658. template<>
  659. struct hash<stacktrace_entry>
  660. {
  661. size_t
  662. operator()(const stacktrace_entry& __f) const noexcept
  663. {
  664. using __h = hash<stacktrace_entry::native_handle_type>;
  665. return __h()(__f.native_handle());
  666. }
  667. };
  668. template<typename _Allocator>
  669. struct hash<basic_stacktrace<_Allocator>>
  670. {
  671. size_t
  672. operator()(const basic_stacktrace<_Allocator>& __st) const noexcept
  673. {
  674. hash<stacktrace_entry::native_handle_type> __h;
  675. size_t __val = _Hash_impl::hash(__st.size());
  676. for (const auto& __f : __st)
  677. __val = _Hash_impl::__hash_combine(__h(__f), __val);
  678. return __val;
  679. }
  680. };
  681. _GLIBCXX_END_NAMESPACE_VERSION
  682. } // namespace std
  683. #endif // C++23
  684. #endif /* _GLIBCXX_STACKTRACE */