Changeset View
Standalone View
libcxx/include/exception
Show First 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | |||||||||||||||
class _LIBCPP_TYPE_VIS exception_ptr; | class _LIBCPP_TYPE_VIS exception_ptr; | ||||||||||||||
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | ||||||||||||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | ||||||||||||||
#ifndef _LIBCPP_ABI_MICROSOFT | #ifndef _LIBCPP_ABI_MICROSOFT | ||||||||||||||
// Previously, the copy constructor, assignment operator, and destructor of | |||||||||||||||
Mordante: I would like some comment describing this `_LIBCPP_EXCEPTION_PTR_GNU_INLINE` magic. Reading the… | |||||||||||||||
// exception_ptr were defined out-of-line, which prevented useful compiler | |||||||||||||||
We should validate whether the compiler supports this attribute. Mordante: We should validate whether the compiler supports this attribute. | |||||||||||||||
The documentation seems to imply that either __GNUC_GNU_INLINE__ or __GNUC_STDC_INLINE__ will be defined if the __gnu_inline__ attribute is supported, so that's what I am now checking for. Let me know if you had something else in mind. fwolff: The [[ https://clang.llvm.org/docs/AttributeReference.html#gnu-inline | documentation ]] seems… | |||||||||||||||
// optimizations (especially for the case where the exception_ptr is known to | |||||||||||||||
// be empty). Changing the out-of-line definitions to inline definitions is an | |||||||||||||||
// ABI break, however; to prevent this, we have to make sure the symbols | |||||||||||||||
// remain available in the libc++ library, in addition to being defined inline | |||||||||||||||
// here in this header. To this end, we use the __gnu_inline__ attribute via the | |||||||||||||||
I think you mean the __gnu_inline__ attribute here. philnik: I think you mean the `__gnu_inline__` attribute here. | |||||||||||||||
// _LIBCPP_EXCEPTION_PTR_GNU_INLINE macro: The macro is defined as empty in | |||||||||||||||
// src/exception.cpp, forcing the definitions of the aforementioned functions to | |||||||||||||||
// be emitted and included in the library. When users of libc++ (re)compile their | |||||||||||||||
Do you mean _LIBCPP_EXCEPTION_PTR_GNU_INLINE here? If yes, please just put it here. It's a bit confusing otherwise. philnik: Do you mean `_LIBCPP_EXCEPTION_PTR_GNU_INLINE` here? If yes, please just put it here. It's a… | |||||||||||||||
// code, however, the _LIBCPP_EXCEPTION_PTR_GNU_INLINE macro won't be defined, | |||||||||||||||
// and thus the __gnu_inline__ attribute will suppress generation of these | |||||||||||||||
__gnu_inline__ doesn't force the functions to be inlined. It disables the generation of the functions. philnik: `__gnu_inline__` doesn't force the functions to be inlined. It disables the generation of the… | |||||||||||||||
// functions while making their definitions available for inlining. | |||||||||||||||
#ifndef _LIBCPP_EXCEPTION_PTR_GNU_INLINE | |||||||||||||||
#if !__has_attribute(__gnu_inline__) | |||||||||||||||
You can use __has_attribute(__gnu_inline__) to check if the compiler supports it. That also works for any other attribute. philnik: You can use `__has_attribute(__gnu_inline__)` to check if the compiler supports it. That also… | |||||||||||||||
#error "this compiler does not appear to support the __gnu_inline__ attribute!" | |||||||||||||||
#endif | |||||||||||||||
#ifndef __GLIBCXX__ | |||||||||||||||
#define _LIBCPP_EXCEPTION_PTR_GNU_INLINE __attribute__((__gnu_inline__)) inline | |||||||||||||||
#else | |||||||||||||||
#define _LIBCPP_EXCEPTION_PTR_GNU_INLINE /*empty*/ | |||||||||||||||
#endif | |||||||||||||||
#endif | |||||||||||||||
_LIBCPP_DIAGNOSTIC_PUSH | |||||||||||||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgnu-inline-cpp-without-extern") | |||||||||||||||
class _LIBCPP_TYPE_VIS exception_ptr | class _LIBCPP_TYPE_VIS exception_ptr | ||||||||||||||
{ | { | ||||||||||||||
void* __ptr_; | void* __ptr_; | ||||||||||||||
#ifndef __GLIBCXX__ | |||||||||||||||
void __incr_refcount() _NOEXCEPT; | |||||||||||||||
void __decr_refcount() _NOEXCEPT; | |||||||||||||||
#endif | |||||||||||||||
public: | public: | ||||||||||||||
_LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} | _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} | ||||||||||||||
_LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} | _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} | ||||||||||||||
exception_ptr(const exception_ptr&) _NOEXCEPT; | _LIBCPP_EXCEPTION_PTR_GNU_INLINE exception_ptr(const exception_ptr&) _NOEXCEPT; | ||||||||||||||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; | _LIBCPP_EXCEPTION_PTR_GNU_INLINE exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; | ||||||||||||||
~exception_ptr() _NOEXCEPT; | _LIBCPP_EXCEPTION_PTR_GNU_INLINE ~exception_ptr() _NOEXCEPT; | ||||||||||||||
_LIBCPP_INLINE_VISIBILITY exception_ptr(exception_ptr&& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { | |||||||||||||||
Same at line 167. Mordante: Same at line 167. | |||||||||||||||
__rhs.__ptr_ = nullptr; | |||||||||||||||
} | |||||||||||||||
// Move assignment is not available for the glibcxx ABI because it | |||||||||||||||
// doesn't have __decr_refcount(). | |||||||||||||||
#ifndef __GLIBCXX__ | |||||||||||||||
_LIBCPP_INLINE_VISIBILITY exception_ptr& operator=(exception_ptr&& __rhs) _NOEXCEPT { | |||||||||||||||
if (__ptr_ != nullptr) | |||||||||||||||
__decr_refcount(); | |||||||||||||||
__ptr_ = __rhs.__ptr_; | |||||||||||||||
__rhs.__ptr_ = nullptr; | |||||||||||||||
return *this; | |||||||||||||||
} | |||||||||||||||
#endif | |||||||||||||||
_LIBCPP_INLINE_VISIBILITY void swap(exception_ptr& __rhs) _NOEXCEPT { | |||||||||||||||
void *__tmp = __ptr_; | |||||||||||||||
__ptr_ = __rhs.__ptr_; | |||||||||||||||
__rhs.__ptr_ = __tmp; | |||||||||||||||
} | |||||||||||||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT | ||||||||||||||
{return __ptr_ != nullptr;} | {return __ptr_ != nullptr;} | ||||||||||||||
friend _LIBCPP_INLINE_VISIBILITY | friend _LIBCPP_INLINE_VISIBILITY | ||||||||||||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | ||||||||||||||
{return __x.__ptr_ == __y.__ptr_;} | {return __x.__ptr_ == __y.__ptr_;} | ||||||||||||||
friend _LIBCPP_INLINE_VISIBILITY | friend _LIBCPP_INLINE_VISIBILITY | ||||||||||||||
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | ||||||||||||||
{return !(__x == __y);} | {return !(__x == __y);} | ||||||||||||||
friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | ||||||||||||||
friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | ||||||||||||||
}; | }; | ||||||||||||||
// If __GLIBCXX__ is defined, the exception_ptr from libsupc++ is used (which | |||||||||||||||
// works because it happens to have the same layout as our exception_ptr). | |||||||||||||||
// The constructor, assignment operator, and destructor should just delegate | |||||||||||||||
// to the libsupc++ implementations then, so we don't provide definitions for | |||||||||||||||
// them here. | |||||||||||||||
#ifndef __GLIBCXX__ | |||||||||||||||
_LIBCPP_EXCEPTION_PTR_GNU_INLINE | |||||||||||||||
exception_ptr::exception_ptr(const exception_ptr& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { | |||||||||||||||
if (__rhs.__ptr_ != nullptr) | |||||||||||||||
__incr_refcount(); | |||||||||||||||
} | |||||||||||||||
_LIBCPP_EXCEPTION_PTR_GNU_INLINE | |||||||||||||||
exception_ptr& exception_ptr::operator=(const exception_ptr& __rhs) _NOEXCEPT { | |||||||||||||||
if (__ptr_ != __rhs.__ptr_) { | |||||||||||||||
if (__ptr_ != nullptr) | |||||||||||||||
__decr_refcount(); | |||||||||||||||
__ptr_ = __rhs.__ptr_; | |||||||||||||||
if (__ptr_ != nullptr) | |||||||||||||||
__incr_refcount(); | |||||||||||||||
} | |||||||||||||||
return *this; | |||||||||||||||
} | |||||||||||||||
_LIBCPP_EXCEPTION_PTR_GNU_INLINE | |||||||||||||||
I don't think that the comment is necessary here, but I also don't object. philnik: I don't think that the comment is necessary here, but I also don't object. | |||||||||||||||
exception_ptr::~exception_ptr() _NOEXCEPT { | |||||||||||||||
if (__ptr_ != nullptr) | |||||||||||||||
__decr_refcount(); | |||||||||||||||
} | |||||||||||||||
philnik: | |||||||||||||||
#endif // __GLIBCXX__ | |||||||||||||||
_LIBCPP_DIAGNOSTIC_POP // pops CLANG_DIAGNOSTIC_IGNORED("-Wgnu-inline-cpp-without-extern") | |||||||||||||||
inline _LIBCPP_INLINE_VISIBILITY void | |||||||||||||||
swap(exception_ptr& __lhs, exception_ptr& __rhs) _NOEXCEPT { | |||||||||||||||
__lhs.swap(__rhs); | |||||||||||||||
} | |||||||||||||||
template<class _Ep> | template<class _Ep> | ||||||||||||||
_LIBCPP_INLINE_VISIBILITY exception_ptr | _LIBCPP_INLINE_VISIBILITY exception_ptr | ||||||||||||||
make_exception_ptr(_Ep __e) _NOEXCEPT | make_exception_ptr(_Ep __e) _NOEXCEPT | ||||||||||||||
{ | { | ||||||||||||||
#ifndef _LIBCPP_NO_EXCEPTIONS | #ifndef _LIBCPP_NO_EXCEPTIONS | ||||||||||||||
try | try | ||||||||||||||
{ | { | ||||||||||||||
throw __e; | throw __e; | ||||||||||||||
▲ Show 20 Lines • Show All 153 Lines • Show Last 20 Lines |
I would like some comment describing this _LIBCPP_EXCEPTION_PTR_GNU_INLINE magic. Reading the other comments in this review make it clear, could you add short summary of that information here?