mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 03:32:35 +08:00
[libc++] Implement exception_ptr on Windows
Summary: This patch implements exception_ptr on Windows using the `__ExceptionPtrFoo` functions provided by MSVC. The `__ExceptionPtrFoo` functions are defined inside the C++ standard library, `msvcprt`, which is unfortunate because it requires libc++ to link to the MSVC STL. However this doesn't seem to cause any immediate problems. However to be safe I kept all usages within the libc++ dylib so that user programs wouldn't have to link to MSVCPRT as well. Note there are still 2 outstanding exception_ptr/nested_exception test failures. * `current_exception.pass.cpp` needs to be rewritten for the Windows exception_ptr semantics which copy the exception every time. * `rethrow_if_nested.pass.cpp` need investigation. It hits a stack overflow, likely from recursion. This patch also gets most of the `<future>` tests passing as well. Reviewers: mclow.lists, compnerd, bcraig, rmaprath, majnemer, BillyONeal, STL_MSFT Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D32927 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@302393 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -134,23 +134,26 @@ 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
|
||||||
|
|
||||||
class _LIBCPP_TYPE_VIS exception_ptr
|
class _LIBCPP_TYPE_VIS exception_ptr
|
||||||
{
|
{
|
||||||
void* __ptr_;
|
void* __ptr_;
|
||||||
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;
|
exception_ptr(const exception_ptr&) _NOEXCEPT;
|
||||||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
|
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
|
||||||
~exception_ptr() _NOEXCEPT;
|
~exception_ptr() _NOEXCEPT;
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
|
||||||
_LIBCPP_EXPLICIT
|
{return __ptr_ != nullptr;}
|
||||||
operator bool() const _NOEXCEPT {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);}
|
||||||
@@ -178,6 +181,54 @@ make_exception_ptr(_Ep __e) _NOEXCEPT
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // _LIBCPP_ABI_MICROSOFT
|
||||||
|
|
||||||
|
class _LIBCPP_TYPE_VIS exception_ptr
|
||||||
|
{
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||||
|
#endif
|
||||||
|
void* __ptr1_;
|
||||||
|
void* __ptr2_;
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT;
|
||||||
|
};
|
||||||
|
|
||||||
|
_LIBCPP_FUNC_VIS
|
||||||
|
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;
|
||||||
|
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
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 p);
|
||||||
|
|
||||||
|
// This is a built-in template function which automagically extracts the required
|
||||||
|
// information.
|
||||||
|
template <class _E> void *__GetExceptionInfo(_E);
|
||||||
|
|
||||||
|
template<class _Ep>
|
||||||
|
exception_ptr
|
||||||
|
make_exception_ptr(_Ep __e) _NOEXCEPT
|
||||||
|
{
|
||||||
|
return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _LIBCPP_ABI_MICROSOFT
|
||||||
// nested_exception
|
// nested_exception
|
||||||
|
|
||||||
class _LIBCPP_EXCEPTION_ABI nested_exception
|
class _LIBCPP_EXCEPTION_ABI nested_exception
|
||||||
|
@@ -121,6 +121,7 @@ if (LIBCXX_TARGETING_MSVC)
|
|||||||
add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime
|
add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime
|
||||||
add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime
|
add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime
|
||||||
add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files
|
add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files
|
||||||
|
add_library_flags(msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
|
||||||
# Required for standards-complaint wide character formatting functions
|
# Required for standards-complaint wide character formatting functions
|
||||||
# (e.g. `printfw`/`scanfw`)
|
# (e.g. `printfw`/`scanfw`)
|
||||||
add_library_flags(iso_stdio_wide_specifiers)
|
add_library_flags(iso_stdio_wide_specifiers)
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#if defined(_LIBCPP_ABI_MICROSOFT)
|
#if defined(_LIBCPP_ABI_MICROSOFT)
|
||||||
#include "support/runtime/exception_msvc.ipp"
|
#include "support/runtime/exception_msvc.ipp"
|
||||||
#include "support/runtime/exception_pointer_unimplemented.ipp"
|
#include "support/runtime/exception_pointer_msvc.ipp"
|
||||||
#elif defined(_LIBCPPABI_VERSION)
|
#elif defined(_LIBCPPABI_VERSION)
|
||||||
#include "support/runtime/exception_libcxxabi.ipp"
|
#include "support/runtime/exception_libcxxabi.ipp"
|
||||||
#include "support/runtime/exception_pointer_cxxabi.ipp"
|
#include "support/runtime/exception_pointer_cxxabi.ipp"
|
||||||
|
94
src/support/runtime/exception_pointer_msvc.ipp
Normal file
94
src/support/runtime/exception_pointer_msvc.ipp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(_Out_ void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCopy(_Out_ void*,
|
||||||
|
_In_ const void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrAssign(_Inout_ void*, _In_ const void*);
|
||||||
|
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrCompare(_In_ const void*, _In_ const void*);
|
||||||
|
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrToBool(_In_ const void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrSwap(_Inout_ void*,
|
||||||
|
_Inout_ void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrCurrentException(_Out_ void*);
|
||||||
|
[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrRethrow(_In_ const void*);
|
||||||
|
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||||
|
__ExceptionPtrCopyException(_Inout_ void*, _In_ const void*, _In_ const void*);
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||||
|
exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||||
|
|
||||||
|
exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT {
|
||||||
|
__ExceptionPtrCopy(this, &__other);
|
||||||
|
}
|
||||||
|
exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT {
|
||||||
|
__ExceptionPtrAssign(this, &__other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT {
|
||||||
|
exception_ptr dummy;
|
||||||
|
__ExceptionPtrAssign(this, &dummy);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); }
|
||||||
|
|
||||||
|
exception_ptr::operator bool() const _NOEXCEPT {
|
||||||
|
return __ExceptionPtrToBool(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
|
||||||
|
return __ExceptionPtrCompare(&__x, &__y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT {
|
||||||
|
__ExceptionPtrSwap(&rhs, &lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
|
||||||
|
exception_ptr __ret = nullptr;
|
||||||
|
if (__ptr)
|
||||||
|
__ExceptionPtrCopyException(&__ret, __except, __ptr);
|
||||||
|
return __ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_ptr current_exception() _NOEXCEPT {
|
||||||
|
exception_ptr __ret;
|
||||||
|
__ExceptionPtrCurrentException(&__ret);
|
||||||
|
return __ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_NORETURN
|
||||||
|
void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
|
||||||
|
|
||||||
|
nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {}
|
||||||
|
|
||||||
|
nested_exception::~nested_exception() _NOEXCEPT {}
|
||||||
|
|
||||||
|
_LIBCPP_NORETURN
|
||||||
|
void nested_exception::rethrow_nested() const {
|
||||||
|
if (__ptr_ == nullptr)
|
||||||
|
terminate();
|
||||||
|
rethrow_exception(__ptr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace std
|
@@ -6,10 +6,6 @@
|
|||||||
// Source Licenses. See LICENSE.TXT for details.
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
|
||||||
|
|
||||||
// This test depends on std::exception_ptr which has not yet been implemented.
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// This test depends on std::exception_ptr which has not yet been implemented.
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// UNSUPPORTED: libcpp-has-no-threads
|
// UNSUPPORTED: libcpp-has-no-threads
|
||||||
// UNSUPPORTED: c++98, c++03
|
// UNSUPPORTED: c++98, c++03
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
// class nested_exception;
|
// class nested_exception;
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
// class nested_exception;
|
// class nested_exception;
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
// class nested_exception;
|
// class nested_exception;
|
||||||
|
@@ -7,10 +7,11 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
|
|
||||||
|
// This test fails due to a stack overflow
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
// XFAIL: LIBCXX-WINDOWS-FIXME
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
// class nested_exception;
|
// class nested_exception;
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
|
@@ -7,7 +7,8 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
// This test needs to be rewritten for the Windows exception_ptr semantics
|
||||||
|
// which copy the exception each time the exception_ptr is copied.
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
// XFAIL: LIBCXX-WINDOWS-FIXME
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
// typedef unspecified exception_ptr;
|
// typedef unspecified exception_ptr;
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
@@ -41,7 +38,12 @@ int main()
|
|||||||
}
|
}
|
||||||
catch (const A& a)
|
catch (const A& a)
|
||||||
{
|
{
|
||||||
|
#ifndef _LIBCPP_ABI_MICROSOFT
|
||||||
assert(A::constructed == 1);
|
assert(A::constructed == 1);
|
||||||
|
#else
|
||||||
|
// On Windows exception_ptr copies the exception
|
||||||
|
assert(A::constructed == 2);
|
||||||
|
#endif
|
||||||
assert(p != nullptr);
|
assert(p != nullptr);
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
assert(p == nullptr);
|
assert(p == nullptr);
|
||||||
@@ -50,4 +52,5 @@ int main()
|
|||||||
}
|
}
|
||||||
assert(A::constructed == 0);
|
assert(A::constructed == 0);
|
||||||
}
|
}
|
||||||
|
assert(A::constructed == 0);
|
||||||
}
|
}
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// exception_ptr has not been implemented on Windows
|
|
||||||
// XFAIL: LIBCXX-WINDOWS-FIXME
|
|
||||||
|
|
||||||
// UNSUPPORTED: libcpp-no-exceptions
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
// <exception>
|
// <exception>
|
||||||
|
|
||||||
@@ -49,7 +46,12 @@ int main()
|
|||||||
}
|
}
|
||||||
catch (const A& a)
|
catch (const A& a)
|
||||||
{
|
{
|
||||||
|
#ifndef _LIBCPP_ABI_MICROSOFT
|
||||||
assert(A::constructed == 1);
|
assert(A::constructed == 1);
|
||||||
|
#else
|
||||||
|
// On Windows the exception_ptr copies the exception
|
||||||
|
assert(A::constructed == 2);
|
||||||
|
#endif
|
||||||
assert(p != nullptr);
|
assert(p != nullptr);
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
assert(p == nullptr);
|
assert(p == nullptr);
|
||||||
@@ -58,4 +60,5 @@ int main()
|
|||||||
}
|
}
|
||||||
assert(A::constructed == 0);
|
assert(A::constructed == 0);
|
||||||
}
|
}
|
||||||
|
assert(A::constructed == 0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user