xref: /llvm-project/libcxx/include/__exception/exception.h (revision 70248920fcd804a5825ecf69f24b96a7e340afe6)
143562287SNikolas Klauser //===----------------------------------------------------------------------===//
243562287SNikolas Klauser //
343562287SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
443562287SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
543562287SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
643562287SNikolas Klauser //
743562287SNikolas Klauser //===----------------------------------------------------------------------===//
843562287SNikolas Klauser 
943562287SNikolas Klauser #ifndef _LIBCPP___EXCEPTION_EXCEPTION_H
1043562287SNikolas Klauser #define _LIBCPP___EXCEPTION_EXCEPTION_H
1143562287SNikolas Klauser 
1243562287SNikolas Klauser #include <__config>
1343562287SNikolas Klauser 
1443562287SNikolas Klauser // <vcruntime_exception.h> defines its own std::exception and std::bad_exception types,
1543562287SNikolas Klauser // which we use in order to be ABI-compatible with other STLs on Windows.
1643562287SNikolas Klauser #if defined(_LIBCPP_ABI_VCRUNTIME)
1743562287SNikolas Klauser #  include <vcruntime_exception.h>
1843562287SNikolas Klauser #endif
1943562287SNikolas Klauser 
2043562287SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2143562287SNikolas Klauser #  pragma GCC system_header
2243562287SNikolas Klauser #endif
2343562287SNikolas Klauser 
2443562287SNikolas Klauser namespace std { // purposefully not using versioning namespace
2543562287SNikolas Klauser 
2643562287SNikolas Klauser #if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0)
2743562287SNikolas Klauser // The std::exception class was already included above, but we're explicit about this condition here for clarity.
2843562287SNikolas Klauser 
2943562287SNikolas Klauser #elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
3043562287SNikolas Klauser // However, <vcruntime_exception.h> does not define std::exception and std::bad_exception
3143562287SNikolas Klauser // when _HAS_EXCEPTIONS == 0.
3243562287SNikolas Klauser //
3343562287SNikolas Klauser // Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0
3443562287SNikolas Klauser // (after all those are simply types like any other), we define an ABI-compatible version
3543562287SNikolas Klauser // of the VCRuntime std::exception and std::bad_exception types in that mode.
3643562287SNikolas Klauser 
3743562287SNikolas Klauser struct __std_exception_data {
3843562287SNikolas Klauser   char const* _What;
3943562287SNikolas Klauser   bool _DoFree;
4043562287SNikolas Klauser };
4143562287SNikolas Klauser 
4243562287SNikolas Klauser class exception { // base of all library exceptions
4343562287SNikolas Klauser public:
4443562287SNikolas Klauser   exception() _NOEXCEPT : __data_() {}
4543562287SNikolas Klauser 
4643562287SNikolas Klauser   explicit exception(char const* __message) _NOEXCEPT : __data_() {
4743562287SNikolas Klauser     __data_._What   = __message;
4843562287SNikolas Klauser     __data_._DoFree = true;
4943562287SNikolas Klauser   }
5043562287SNikolas Klauser 
5143562287SNikolas Klauser   exception(exception const&) _NOEXCEPT {}
5243562287SNikolas Klauser 
5343562287SNikolas Klauser   exception& operator=(exception const&) _NOEXCEPT { return *this; }
5443562287SNikolas Klauser 
5543562287SNikolas Klauser   virtual ~exception() _NOEXCEPT {}
5643562287SNikolas Klauser 
5743562287SNikolas Klauser   virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; }
5843562287SNikolas Klauser 
5943562287SNikolas Klauser private:
6043562287SNikolas Klauser   __std_exception_data __data_;
6143562287SNikolas Klauser };
6243562287SNikolas Klauser 
6343562287SNikolas Klauser class bad_exception : public exception {
6443562287SNikolas Klauser public:
6543562287SNikolas Klauser   bad_exception() _NOEXCEPT : exception("bad exception") {}
6643562287SNikolas Klauser };
6743562287SNikolas Klauser 
6843562287SNikolas Klauser #else  // !defined(_LIBCPP_ABI_VCRUNTIME)
6943562287SNikolas Klauser // On all other platforms, we define our own std::exception and std::bad_exception types
7043562287SNikolas Klauser // regardless of whether exceptions are turned on as a language feature.
7143562287SNikolas Klauser 
72f1ea0b11SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI exception {
7343562287SNikolas Klauser public:
7443562287SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI exception() _NOEXCEPT {}
7543562287SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI exception(const exception&) _NOEXCEPT            = default;
76*70248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default;
7743562287SNikolas Klauser 
7843562287SNikolas Klauser   virtual ~exception() _NOEXCEPT;
7943562287SNikolas Klauser   virtual const char* what() const _NOEXCEPT;
8043562287SNikolas Klauser };
8143562287SNikolas Klauser 
82f1ea0b11SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
8343562287SNikolas Klauser public:
8443562287SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI bad_exception() _NOEXCEPT {}
85*70248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT            = default;
86*70248920SIgor Zhukov   _LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default;
8743562287SNikolas Klauser   ~bad_exception() _NOEXCEPT override;
8843562287SNikolas Klauser   const char* what() const _NOEXCEPT override;
8943562287SNikolas Klauser };
9043562287SNikolas Klauser #endif // !_LIBCPP_ABI_VCRUNTIME
9143562287SNikolas Klauser 
9243562287SNikolas Klauser } // namespace std
9343562287SNikolas Klauser 
9443562287SNikolas Klauser #endif // _LIBCPP___EXCEPTION_EXCEPTION_H
95