Martin Storsjö f355a57728
[libcxx] Initialize vcruntime __std_exception_data in the exception copy ctor (#144329)
This fixes failures in a number of tests, in the
clang-cl-no-vcruntime configuration (where libcxx provides dummy, no-op
replacements of some vcruntime base exception classes), if building with
optimization enabled.

Previously, with optimization enabled, the compiler concluded that these
fields would be uninitialized at the points of asserts in the tests.

This fixes the following tests in this configuration:

llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.dynamic/alloc.errors/bad.alloc/bad_alloc.pass.cpp
llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.dynamic/alloc.errors/new.badlength/bad_array_new_length.pass.cpp
llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.exception/bad.exception/bad_exception.pass.cpp
llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.exception/exception/exception.pass.cpp
llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.rtti/bad.cast/bad_cast.pass.cpp
llvm-libc++-shared-no-vcruntime-clangcl.cfg.in ::
std/language.support/support.rtti/bad.typeid/bad_typeid.pass.cpp
2025-08-05 22:11:27 +03:00

95 lines
3.2 KiB
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___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
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
#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 : __data_() {}
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_EXPORTED_FROM_ABI exception {
public:
_LIBCPP_HIDE_FROM_ABI exception() _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI exception(const exception&) _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default;
virtual ~exception() _NOEXCEPT;
virtual const char* what() const _NOEXCEPT;
};
class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
public:
_LIBCPP_HIDE_FROM_ABI bad_exception() _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default;
~bad_exception() _NOEXCEPT override;
const char* what() const _NOEXCEPT override;
};
#endif // !_LIBCPP_ABI_VCRUNTIME
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
#endif // _LIBCPP___EXCEPTION_EXCEPTION_H