xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/stacktrace (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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