Skip to content

Commit

Permalink
[libc++] Granularize <exception>
Browse files Browse the repository at this point in the history
This patch also updates the moved code to the new style (i.e. formatted, replaced marcos and typedefs)

Reviewed By: ldionne, #libc

Spies: arichardson, libcxx-commits

Differential Revision: https://reviews.llvm.org/D145095
  • Loading branch information
philnik777 committed Mar 12, 2023
1 parent 55f8a28 commit 4356228
Show file tree
Hide file tree
Showing 29 changed files with 418 additions and 292 deletions.
5 changes: 5 additions & 0 deletions libcxx/include/CMakeLists.txt
Expand Up @@ -297,6 +297,11 @@ set(files
__debug
__debug_utils/randomize_range.h
__errc
__exception/exception.h
__exception/exception_ptr.h
__exception/nested_exception.h
__exception/operations.h
__exception/terminate.h
__expected/bad_expected_access.h
__expected/expected.h
__expected/unexpect.h
Expand Down
91 changes: 91 additions & 0 deletions libcxx/include/__exception/exception.h
@@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
//
// 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___EXCEPTION_EXCEPTION_H
#define _LIBCPP___EXCEPTION_EXCEPTION_H

#include <__config>

// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types,
// which we use in order to be ABI-compatible with other STLs on Windows.
#if defined(_LIBCPP_ABI_VCRUNTIME)
# include <vcruntime_exception.h>
#endif

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

namespace std { // purposefully not using versioning namespace

#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0)
// The std::exception class was already included above, but we're explicit about this condition here for clarity.

#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception
// when _HAS_EXCEPTIONS == 0.
//
// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0
// (after all those are simply types like any other), we define an ABI-compatible version
// of the VCRuntime std::exception and std::bad_exception types in that mode.

struct __std_exception_data {
char const* _What;
bool _DoFree;
};

class exception { // base of all library exceptions
public:
exception() _NOEXCEPT : __data_() {}

explicit exception(char const* __message) _NOEXCEPT : __data_() {
__data_._What = __message;
__data_._DoFree = true;
}

exception(exception const&) _NOEXCEPT {}

exception& operator=(exception const&) _NOEXCEPT { return *this; }

virtual ~exception() _NOEXCEPT {}

virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; }

private:
__std_exception_data __data_;
};

class bad_exception : public exception {
public:
bad_exception() _NOEXCEPT : exception("bad exception") {}
};

#else // !defined(_LIBCPP_ABI_VCRUNTIME)
// On all other platforms, we define our own std::exception and std::bad_exception types
// regardless of whether exceptions are turned on as a language feature.

class _LIBCPP_EXCEPTION_ABI exception {
public:
_LIBCPP_HIDE_FROM_ABI exception() _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI exception(const exception&) _NOEXCEPT = default;

virtual ~exception() _NOEXCEPT;
virtual const char* what() const _NOEXCEPT;
};

class _LIBCPP_EXCEPTION_ABI bad_exception : public exception {
public:
_LIBCPP_HIDE_FROM_ABI bad_exception() _NOEXCEPT {}
~bad_exception() _NOEXCEPT override;
const char* what() const _NOEXCEPT override;
};
#endif // !_LIBCPP_ABI_VCRUNTIME

} // namespace std

#endif // _LIBCPP___EXCEPTION_EXCEPTION_H
108 changes: 108 additions & 0 deletions libcxx/include/__exception/exception_ptr.h
@@ -0,0 +1,108 @@
//===----------------------------------------------------------------------===//
//
// 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___EXCEPTION_EXCEPTION_PTR_H
#define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H

#include <__config>
#include <__exception/operations.h>
#include <cstddef>
#include <cstdlib>

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

namespace std { // purposefully not using versioning namespace

#ifndef _LIBCPP_ABI_MICROSOFT

class _LIBCPP_TYPE_VIS exception_ptr {
void* __ptr_;

public:
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}

exception_ptr(const exception_ptr&) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;

_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; }

friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
return __x.__ptr_ == __y.__ptr_;
}

friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
return !(__x == __y);
}

friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
};

template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try {
throw __e;
} catch (...) {
return current_exception();
}
# else
((void)__e);
std::abort();
# endif
}

#else // _LIBCPP_ABI_MICROSOFT

class _LIBCPP_TYPE_VIS exception_ptr {
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field")
void* __ptr1_;
void* __ptr2_;
_LIBCPP_DIAGNOSTIC_POP

public:
exception_ptr() _NOEXCEPT;
exception_ptr(nullptr_t) _NOEXCEPT;
exception_ptr(const exception_ptr& __other) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
exception_ptr& operator=(nullptr_t) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;
explicit operator bool() const _NOEXCEPT;
};

_LIBCPP_FUNC_VIS bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;

inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
return !(__x == __y);
}

_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT;

_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void* __except, const void* __ptr);
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);

// This is a built-in template function which automagically extracts the required
// information.
template <class _E>
void* __GetExceptionInfo(_E);

template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
return __copy_exception_ptr(std::addressof(__e), __GetExceptionInfo(__e));
}

#endif // _LIBCPP_ABI_MICROSOFT
} // namespace std

#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
101 changes: 101 additions & 0 deletions libcxx/include/__exception/nested_exception.h
@@ -0,0 +1,101 @@
//===----------------------------------------------------------------------===//
//
// 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___EXCEPTION_NESTED_EXCEPTION_H
#define _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H

#include <__config>
#include <__exception/exception_ptr.h>
#include <__memory/addressof.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_base_of.h>
#include <__type_traits/is_class.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_copy_constructible.h>
#include <__type_traits/is_final.h>
#include <__type_traits/is_polymorphic.h>
#include <__utility/forward.h>
#include <cstddef>

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

namespace std { // purposefully not using versioning namespace

class _LIBCPP_EXCEPTION_ABI nested_exception {
exception_ptr __ptr_;

public:
nested_exception() _NOEXCEPT;
// nested_exception(const nested_exception&) noexcept = default;
// nested_exception& operator=(const nested_exception&) noexcept = default;
virtual ~nested_exception() _NOEXCEPT;

// access functions
_LIBCPP_NORETURN void rethrow_nested() const;
_LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
};

template <class _Tp>
struct __nested : public _Tp, public nested_exception {
_LIBCPP_HIDE_FROM_ABI explicit __nested(const _Tp& __t) : _Tp(__t) {}
};

#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
template <class _Tp, class _Up, bool>
struct __throw_with_nested;

template <class _Tp, class _Up>
struct __throw_with_nested<_Tp, _Up, true> {
_LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) {
throw __nested<_Up>(std::forward<_Tp>(__t));
}
};

template <class _Tp, class _Up>
struct __throw_with_nested<_Tp, _Up, false> {
_LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) { throw std::forward<_Tp>(__t); }
};
#endif

template <class _Tp>
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void throw_with_nested(_Tp&& __t) {
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
typedef typename decay<_Tp>::type _Up;
static_assert(is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible");
__throw_with_nested<_Tp,
_Up,
is_class<_Up>::value && !is_base_of<nested_exception, _Up>::value &&
!__libcpp_is_final<_Up>::value>::__do_throw(std::forward<_Tp>(__t));
#else
((void)__t);
// FIXME: Make this abort
#endif
}

template <class _From, class _To>
struct __can_dynamic_cast
: _BoolConstant< is_polymorphic<_From>::value &&
(!is_base_of<_To, _From>::value || is_convertible<const _From*, const _To*>::value)> {};

template <class _Ep>
inline _LIBCPP_HIDE_FROM_ABI void
rethrow_if_nested(const _Ep& __e, __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) {
const nested_exception* __nep = dynamic_cast<const nested_exception*>(std::addressof(__e));
if (__nep)
__nep->rethrow_nested();
}

template <class _Ep>
inline _LIBCPP_HIDE_FROM_ABI void
rethrow_if_nested(const _Ep&, __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) {}

} // namespace std

#endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H
42 changes: 42 additions & 0 deletions libcxx/include/__exception/operations.h
@@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// 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___EXCEPTION_OPERATIONS_H
#define _LIBCPP___EXCEPTION_OPERATIONS_H

#include <__availability>
#include <__config>
#include <cstddef>

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

namespace std { // purposefully not using versioning namespace
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) || \
defined(_LIBCPP_BUILDING_LIBRARY)
using unexpected_handler = void (*)();
_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT;
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected();
#endif

using terminate_handler = void (*)();
_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;

_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT;

class _LIBCPP_TYPE_VIS exception_ptr;

_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
} // namespace std

#endif // _LIBCPP___EXCEPTION_OPERATIONS_H
22 changes: 22 additions & 0 deletions libcxx/include/__exception/terminate.h
@@ -0,0 +1,22 @@
//===----------------------------------------------------------------------===//
//
// 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___EXCEPTION_TERMINATE_H
#define _LIBCPP___EXCEPTION_TERMINATE_H

#include <__config>

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

namespace std { // purposefully not using versioning namespace
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
} // namespace std

#endif // _LIBCPP___EXCEPTION_TERMINATE_H
1 change: 1 addition & 0 deletions libcxx/include/__format/formatter_integral.h
Expand Up @@ -22,6 +22,7 @@
#include <charconv>
#include <limits>
#include <string>
#include <string_view>

#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <locale>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__iterator/common_iterator.h
Expand Up @@ -25,6 +25,7 @@
#include <__iterator/iter_swap.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/readable_traits.h>
#include <__memory/addressof.h>
#include <__type_traits/is_pointer.h>
#include <__utility/declval.h>
#include <variant>
Expand Down

0 comments on commit 4356228

Please sign in to comment.