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