[libcxx-commits] [libcxx] Add C++23 stacktrace (P0881R7) (PR #136528)

Steve O'Brien via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 16 14:46:41 PDT 2025


================
@@ -0,0 +1,237 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_STACKTRACE_BASIC
+#define _LIBCPP_STACKTRACE_BASIC
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 23
+
+#  include <__functional/hash.h>
+#  include <__fwd/format.h>
+#  include <__iterator/iterator.h>
+#  include <__iterator/reverse_iterator.h>
+#  include <__memory/allocator_traits.h>
+#  include <__memory_resource/polymorphic_allocator.h>
+#  include <__type_traits/is_nothrow_constructible.h>
+#  include <__vector/vector.h>
+#  include <utility>
+
+#  include <__stacktrace/base.h>
+#  include <__stacktrace/entry.h>
+#  include <__stacktrace/to_string.h>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// (19.6.4)
+// Class template basic_stacktrace [stacktrace.basic]
+
+class stacktrace_entry;
+
+template <class _Allocator>
+class _LIBCPP_EXPORTED_FROM_ABI basic_stacktrace : private __stacktrace::base {
+  friend struct hash<basic_stacktrace<_Allocator>>;
+  friend struct __stacktrace::__to_string;
+
+  using _ATraits _LIBCPP_NODEBUG               = allocator_traits<_Allocator>;
+  constexpr static bool __kPropOnCopyAssign    = _ATraits::propagate_on_container_copy_assignment::value;
+  constexpr static bool __kPropOnMoveAssign    = _ATraits::propagate_on_container_move_assignment::value;
+  constexpr static bool __kPropOnSwap          = _ATraits::propagate_on_container_swap::value;
+  constexpr static bool __kAlwaysEqual         = _ATraits::is_always_equal::value;
+  constexpr static bool __kNoThrowDflConstruct = is_nothrow_default_constructible_v<_Allocator>;
+  constexpr static bool __kNoThrowAlloc =
+      noexcept(noexcept(_Allocator().allocate(1)) && noexcept(_Allocator().allocate_at_least(1)));
+
+  [[no_unique_address]]
+  _Allocator __alloc_;
+
+  using __entry_vec _LIBCPP_NODEBUG = vector<stacktrace_entry, _Allocator>;
+  __entry_vec __entries_;
+
+public:
+  // (19.6.4.1)
+  // Overview [stacktrace.basic.overview]
+
+  using value_type      = stacktrace_entry;
+  using const_reference = const value_type&;
+  using reference       = value_type&;
+  using difference_type = ptrdiff_t;
+  using size_type       = size_t;
+  using allocator_type  = _Allocator;
+  using const_iterator  = __entry_vec::const_iterator;
+  using iterator        = const_iterator;
+
+  using reverse_iterator       = std::reverse_iterator<basic_stacktrace::iterator>;
+  using const_reverse_iterator = std::reverse_iterator<basic_stacktrace::const_iterator>;
+
+  // (19.6.4.2)
+  // Creation and assignment [stacktrace.basic.cons]
+
+  _LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
+  current(const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
+    return current(1, /* no __max_depth */ ~0, __caller_alloc);
+  }
+
+  _LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
+  current(size_type __skip, const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
+    return current(__skip + 1, /* no __max_depth */ ~0, __caller_alloc);
+  }
+
+  _LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI static basic_stacktrace
+  current(size_type __skip,
+          size_type __max_depth,
+          const allocator_type& __caller_alloc = allocator_type()) noexcept(__kNoThrowAlloc) {
+    __stacktrace::base __builder(__caller_alloc);
----------------
elsteveogrande wrote:

Thanks @var-const !  I'm 99% sure the implementation is ok but I'll ensure overflow isn't possible.

For this I will do the following (please confirm):

* `_LIBCPP_ASSERT_`*something* to check this within `current`
* add an `XFAIL` test for this, with e.g. `skip=1` and `max_depth=0xffff_ffff_ffff_ffff`
* set `__cpp_lib_hardened_basic_stacktrace` to `202502`


https://github.com/llvm/llvm-project/pull/136528


More information about the libcxx-commits mailing list