Skip to content

Add C++23 stacktrace (P0881R7) #136528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 46 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b287a16
Add C++23 stacktrace
elsteveogrande Jan 16, 2025
52da939
Remove unrelated change
elsteveogrande Apr 21, 2025
c92d736
fix cflag option
elsteveogrande Apr 23, 2025
ffe3cdb
Move stacktrace headers out of experimental
elsteveogrande Apr 21, 2025
a440a46
Move stacktrace srcs out of experimental
elsteveogrande Apr 22, 2025
dab7e01
simplify layout of stacktrace files: condense, collapse
elsteveogrande Apr 23, 2025
0f93c02
Reference papers and issues
elsteveogrande Apr 23, 2025
15992ea
Updates per PR feedback
elsteveogrande Apr 23, 2025
39162cf
Remove newline at end of file: std.compat.cppm.in
elsteveogrande Apr 23, 2025
f9c412d
Committing regenerated files
Apr 23, 2025
1a35918
Address lints for system headers
elsteveogrande Apr 23, 2025
02d2480
Add generated 'stacktrace.version.compile.pass.cpp' test
elsteveogrande Apr 23, 2025
aab978a
Address some errors from gcc regarding inlining
elsteveogrande Apr 23, 2025
658060f
Feature macros + regenerate
elsteveogrande Apr 24, 2025
b2b15f8
Break up tests
elsteveogrande Apr 24, 2025
2a11c50
Minor: formatting
elsteveogrande Apr 24, 2025
4ddfbae
Remove changes not related to this (probably a previous bad merge)
elsteveogrande Apr 24, 2025
6c98f6b
Correcting doc for LIBCXX_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME
elsteveogrande Apr 24, 2025
01faf65
Add C++23 stacktrace
elsteveogrande Jan 16, 2025
f6ee162
Remove unrelated change
elsteveogrande Apr 21, 2025
4b45777
Move stacktrace headers out of experimental
elsteveogrande Apr 21, 2025
8fef91f
Move stacktrace srcs out of experimental
elsteveogrande Apr 22, 2025
65389c1
simplify layout of stacktrace files: condense, collapse
elsteveogrande Apr 23, 2025
2f12acb
Updates per PR feedback
elsteveogrande Apr 23, 2025
c26efd9
Remove newline at end of file: std.compat.cppm.in
elsteveogrande Apr 23, 2025
63bfca9
Committing regenerated files
Apr 23, 2025
7fb17ca
Address some errors from gcc regarding inlining
elsteveogrande Apr 23, 2025
4560726
Feature macros + regenerate
elsteveogrande Apr 24, 2025
4950562
Break up tests
elsteveogrande Apr 24, 2025
f486936
Remove changes not related to this (probably a previous bad merge)
elsteveogrande Apr 24, 2025
11b74de
Mention URL 'format' task (105257) for TODO's
elsteveogrande May 14, 2025
b651a47
commit new generated files
elsteveogrande May 14, 2025
6680809
formatting
elsteveogrande May 14, 2025
85e36c4
refactor; rework alloc/dealloc, strings; don't use pmr
elsteveogrande May 16, 2025
94b7e2f
regenerated files
elsteveogrande May 19, 2025
eae8d87
formatting
elsteveogrande May 19, 2025
e332628
formatting
elsteveogrande May 19, 2025
f3aab1b
clean up non-ASCII chars from pasted content
elsteveogrande May 19, 2025
e130395
minor: rename a .cpp
elsteveogrande May 20, 2025
27cf220
split up confusing 'utils.h'
elsteveogrande May 20, 2025
c179647
fix windows macros
elsteveogrande May 20, 2025
ac43b8c
break up win impl
elsteveogrande May 20, 2025
c7ca34f
break up other impl's
elsteveogrande May 23, 2025
786afd1
cleanup impl's
elsteveogrande May 23, 2025
b1f6f70
remove placeholder header for formatter
elsteveogrande May 24, 2025
b36616a
end-of-file newline?
elsteveogrande May 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libcxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ option(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS
the shared library they shipped should turn this on and see `include/__configuration/availability.h`
for more details." OFF)

option(LIBCXX_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME
"For C++23 <stacktrace>: whether to allow invocation of `addr2line`, `llvm-addr2line`, or `atos`
at runtime (if it's available in `PATH`) to resolve call-chain addresses in the stacktrace
into source locations, if other methods are not available." ON)

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-shared-gcc.cfg.in")
elseif(MINGW)
Expand Down Expand Up @@ -758,6 +763,7 @@ config_define(${LIBCXX_ENABLE_UNICODE} _LIBCPP_HAS_UNICODE)
config_define(${LIBCXX_ENABLE_WIDE_CHARACTERS} _LIBCPP_HAS_WIDE_CHARACTERS)
config_define(${LIBCXX_ENABLE_TIME_ZONE_DATABASE} _LIBCPP_HAS_TIME_ZONE_DATABASE)
config_define(${LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS} _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS)
config_define(${LIBCXX_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME} _LIBCPP_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME)

# TODO: Remove in LLVM 21. We're leaving an error to make this fail explicitly.
if (LIBCXX_ENABLE_ASSERTIONS)
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_spanstream`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_stacktrace`` *unimplemented*
``__cpp_lib_stacktrace`` ``202011L``
---------------------------------------------------------- -----------------
``__cpp_lib_stdatomic_h`` ``202011L``
---------------------------------------------------------- -----------------
Expand Down
2 changes: 2 additions & 0 deletions libcxx/docs/ReleaseNotes/21.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ Implemented Papers
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github <https://github.com/llvm/llvm-project/issues/118372>`__)
- P3247R2: Deprecate the notion of trivial types (`Github <https://github.com/llvm/llvm-project/issues/118387>`__)
- P0881R7: A Proposal to add stacktrace library (`Github <https://github.com/llvm/llvm-project/issues/105131>`__)
- P2301R1: Add a `pmr` alias for `std::stacktrace` (`Github <https://github.com/llvm/llvm-project/issues/105167>`__)

Improvements and New Features
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
"`LWG3028 <https://wg21.link/LWG3028>`__","Container requirements tables should distinguish ``const`` and non-``const`` variables","2022-11 (Kona)","","",""
"`LWG3118 <https://wg21.link/LWG3118>`__","``fpos`` equality comparison unspecified","2022-11 (Kona)","","",""
"`LWG3177 <https://wg21.link/LWG3177>`__","Limit permission to specialize variable templates to program-defined types","2022-11 (Kona)","|Nothing To Do|","",""
"`LWG3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized","2022-11 (Kona)","","",""
"`LWG3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized","2022-11 (Kona)","|Nothing To Do|","",""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only had a quick look but I think the status should be |Complete| and you also need to add Closes #104998 .

#104998

We don't add an entry to Release Notes for LWG issues.

"`LWG3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly","2022-11 (Kona)","|Complete|","18",""
"`LWG3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators","2022-11 (Kona)","","",""
"`LWG3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor","2022-11 (Kona)","|Complete|","19",""
Expand Down
6 changes: 3 additions & 3 deletions libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"Paper #","Paper Name","Meeting","Status","First released version","Notes"
"`P0881R7 <https://wg21.link/P0881R7>`__","A Proposal to add stacktrace library","2020-11 (Virtual)","","",""
"`P0881R7 <https://wg21.link/P0881R7>`__","A Proposal to add stacktrace library","2020-11 (Virtual)","|Complete|","21",""
"`P0943R6 <https://wg21.link/P0943R6>`__","Support C atomics in C++","2020-11 (Virtual)","|Complete|","15",""
"`P1048R1 <https://wg21.link/P1048R1>`__","A proposal for a type trait to detect scoped enumerations","2020-11 (Virtual)","|Complete|","12",""
"`P1679R3 <https://wg21.link/P1679R3>`__","string contains function","2020-11 (Virtual)","|Complete|","12",""
Expand Down Expand Up @@ -32,7 +32,7 @@
"`P1675R2 <https://wg21.link/P1675R2>`__","``rethrow_exception`` must be allowed to copy","2021-10 (Virtual)","|Nothing To Do|","",""
"`P2077R3 <https://wg21.link/P2077R3>`__","Heterogeneous erasure overloads for associative containers","2021-10 (Virtual)","","",""
"`P2251R1 <https://wg21.link/P2251R1>`__","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","2021-10 (Virtual)","|Complete|","14",""
"`P2301R1 <https://wg21.link/P2301R1>`__","Add a ``pmr`` alias for ``std::stacktrace``","2021-10 (Virtual)","","",""
"`P2301R1 <https://wg21.link/P2301R1>`__","Add a ``pmr`` alias for ``std::stacktrace``","2021-10 (Virtual)","|Complete|","21",""
"`P2321R2 <https://wg21.link/P2321R2>`__","``zip``","2021-10 (Virtual)","|In Progress|","",""
"`P2340R1 <https://wg21.link/P2340R1>`__","Clarifying the status of the 'C headers'","2021-10 (Virtual)","|Nothing To Do|","",""
"`P2393R1 <https://wg21.link/P2393R1>`__","Cleaning up ``integer``-class types","2021-10 (Virtual)","","",""
Expand Down Expand Up @@ -110,7 +110,7 @@
"`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19",""
"`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17",""
"`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17",""
"`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet"
"`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented yet"
"`P2679R2 <https://wg21.link/P2679R2>`__","Fixing ``std::start_lifetime_as`` for arrays","2023-02 (Issaquah)","","",""
"`P2674R1 <https://wg21.link/P2674R1>`__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20",""
"`P2655R3 <https://wg21.link/P2655R3>`__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","","",""
Expand Down
8 changes: 8 additions & 0 deletions libcxx/docs/VendorDocumentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ General purpose options
ship the IANA time zone database. When time zones are not supported,
time zone support in <chrono> will be disabled.

.. option:: LIBCXX_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME:BOOL

**Default**: ``ON``

For C++23 <stacktrace>: whether to allow invocation of ``addr2line``, ``llvm-addr2line``, or ``atos``
at runtime (if it's available in ``PATH``) to resolve call-chain addresses in the stacktrace
into source locations, if other methods are not available.

.. option:: LIBCXX_INSTALL_LIBRARY_DIR:PATH

**Default**: ``lib${LIBCXX_LIBDIR_SUFFIX}``
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,12 @@ set(files
__ranges/views.h
__ranges/zip_view.h
__split_buffer
__stacktrace/base.h
__stacktrace/basic.h
__stacktrace/entry.h
__stacktrace/hash.h
__stacktrace/nonmem.h
__stacktrace/to_string.h
__std_mbstate_t.h
__stop_token/atomic_unique_lock.h
__stop_token/intrusive_list_view.h
Expand Down Expand Up @@ -1048,6 +1054,7 @@ set(files
span
sstream
stack
stacktrace
stdatomic.h
stdbool.h
stddef.h
Expand Down
27 changes: 27 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,33 @@ typedef __char32_t char32_t;
# define _LIBCPP_NOINLINE
# endif

// Some functions, e.g. std::stacktrace::current, need to avoid being
// tail-called by (and tail-calling other) functions, for proper enumeration of
// call-stack frames.
// clang-format off

// Disables tail-call optimization for "outbound" calls
// performed in the function annotated with this attribute.
# if __has_cpp_attribute(_Clang::__disable_tail_calls__)
# define _LIBCPP_NO_TAIL_CALLS_OUT [[_Clang::__disable_tail_calls__]]
# elif __has_cpp_attribute(__gnu__::__optimize__)
# define _LIBCPP_NO_TAIL_CALLS_OUT [[__gnu__::__optimize__("no-optimize-sibling-calls")]]
# else
# define _LIBCPP_NO_TAIL_CALLS_OUT
# endif

// Disables tail-call optimization for "inbound" calls -- that is,
// calls from some other function calling the one having this attribute.
# if __has_cpp_attribute(_Clang::__not_tail_called__)
# define _LIBCPP_NO_TAIL_CALLS_IN [[_Clang::__not_tail_called__]]
# else
# define _LIBCPP_NO_TAIL_CALLS_IN
# endif

// Disable TCO for calls into, and out from, the annotated function.
# define _LIBCPP_NO_TAIL_CALLS _LIBCPP_NO_TAIL_CALLS_IN _LIBCPP_NO_TAIL_CALLS_OUT
// clang-format on

// We often repeat things just for handling wide characters in the library.
// When wide characters are disabled, it can be useful to have a quick way of
// disabling it without having to resort to #if-#endif, which has a larger
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__config_site.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#cmakedefine _LIBCPP_HAS_NO_STD_MODULES
#cmakedefine01 _LIBCPP_HAS_TIME_ZONE_DATABASE
#cmakedefine01 _LIBCPP_INSTRUMENTED_WITH_ASAN
#cmakedefine01 _LIBCPP_STACKTRACE_ALLOW_TOOLS_AT_RUNTIME

// PSTL backends
#cmakedefine _LIBCPP_PSTL_BACKEND_SERIAL
Expand Down
131 changes: 131 additions & 0 deletions libcxx/include/__stacktrace/base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// -*- 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_BUILDER
#define _LIBCPP_STACKTRACE_BUILDER

#include <__config>
#include <__cstddef/byte.h>
#include <__cstddef/size_t.h>
#include <__functional/function.h>
#include <__fwd/format.h>
#include <__fwd/ostream.h>
#include <__memory/allocator_traits.h>
#include <__vector/vector.h>
#include <cstddef>
#include <cstdint>
#include <list>
#include <optional>
#include <string>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

class stacktrace_entry;

namespace __stacktrace {

struct _LIBCPP_HIDE_FROM_ABI alloc final {
function<byte*(size_t)> __alloc_bytes_;
function<void(byte*, size_t)> __dealloc_bytes_;

template <class _Allocator>
alloc(_Allocator __alloc) {
using _AT = allocator_traits<_Allocator>;
using _BA = typename _AT::template rebind_alloc<byte>;
auto __ba = _BA(__alloc);
__alloc_bytes_ = [__ba](size_t __sz) mutable { return __ba.allocate(__sz); };
__dealloc_bytes_ = [__ba](void* __ptr, size_t __sz) mutable { __ba.deallocate((byte*)__ptr, __sz); };
}

template <typename _Tp>
struct Alloc {
function<byte*(size_t)> __alloc_bytes_;
function<void(byte*, size_t)> __dealloc_bytes_;

Alloc(function<byte*(size_t)> __alloc_bytes, function<void(byte*, size_t)> __dealloc_bytes)
: __alloc_bytes_(__alloc_bytes), __dealloc_bytes_(__dealloc_bytes) {}

template <typename _T2 = _Tp>
Alloc(Alloc<_T2> const& __rhs) : Alloc(__rhs.__alloc_bytes_, __rhs.__dealloc_bytes_) {}

using value_type = _Tp;
[[nodiscard]] _Tp* allocate(size_t __sz) { return (_Tp*)__alloc_bytes_(__sz * sizeof(_Tp)); }
void deallocate(_Tp* __ptr, size_t __sz) { __dealloc_bytes_((byte*)__ptr, __sz * sizeof(_Tp)); }

template <typename _A2>
bool operator==(_A2 const& __rhs) const {
return &__rhs == this;
}
};

template <typename _Tp>
Alloc<_Tp> make_alloc() {
return {__alloc_bytes_, __dealloc_bytes_};
}

using str = basic_string<char, char_traits<char>, Alloc<char>>;

template <typename... _Args>
str make_str(_Args... __args) {
return str(std::forward<_Args>(__args)..., make_alloc<char>());
}

template <typename _Tp>
using vec = vector<_Tp, Alloc<_Tp>>;

template <typename _Tp, typename... _Args>
vec<_Tp> make_vec(_Args... __args) {
return vec(std::forward<_Args>(__args)..., make_alloc<_Tp>());
}

template <typename _Tp>
using list = ::std::list<_Tp, Alloc<_Tp>>;

template <typename _Tp, typename... _Args>
list<_Tp> make_list(_Args... __args) {
return list(std::forward<_Args>(__args)..., make_alloc<_Tp>());
}
};

struct _LIBCPP_HIDE_FROM_ABI entry_base {
uintptr_t __addr_actual_{}; // this address, as observed in this current process
uintptr_t __addr_unslid_{}; // address adjusted for ASLR
optional<__stacktrace::alloc::str> __desc_{}; // uses wrapped _Allocator from caller
optional<__stacktrace::alloc::str> __file_{}; // uses wrapped _Allocator from caller
uint_least32_t __line_{};

stacktrace_entry to_stacktrace_entry() const;
};

struct _LIBCPP_HIDE_FROM_ABI builder final {
alloc __alloc_; // wraps the caller-provided allocator
alloc::vec<entry_base> __entries_;
alloc::str __main_prog_path_;

template <class _Allocator>
explicit builder(_Allocator __alloc)
: __alloc_(__alloc), __entries_(__alloc_.make_vec<entry_base>()), __main_prog_path_(__alloc_.make_str()) {}

_LIBCPP_NO_TAIL_CALLS _LIBCPP_NOINLINE _LIBCPP_EXPORTED_FROM_ABI void
build_stacktrace(size_t __skip, size_t __max_depth);
};

} // namespace __stacktrace
_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP_STACKTRACE_BUILDER
Loading
Loading