Skip to content

Commit 3e254a6

Browse files
committedMay 8, 2017
[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 llvm-svn: 302393
1 parent 90a8fc8 commit 3e254a6

16 files changed

+167
-38
lines changed
 

‎libcxx/include/exception

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,23 +134,26 @@ class _LIBCPP_TYPE_VIS exception_ptr;
134134
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
135135
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
136136

137+
#ifndef _LIBCPP_ABI_MICROSOFT
138+
137139
class _LIBCPP_TYPE_VIS exception_ptr
138140
{
139141
void* __ptr_;
140142
public:
141143
_LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
142144
_LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
145+
143146
exception_ptr(const exception_ptr&) _NOEXCEPT;
144147
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
145148
~exception_ptr() _NOEXCEPT;
146149

147-
_LIBCPP_INLINE_VISIBILITY
148-
_LIBCPP_EXPLICIT
149-
operator bool() const _NOEXCEPT {return __ptr_ != nullptr;}
150+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
151+
{return __ptr_ != nullptr;}
150152

151153
friend _LIBCPP_INLINE_VISIBILITY
152154
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
153155
{return __x.__ptr_ == __y.__ptr_;}
156+
154157
friend _LIBCPP_INLINE_VISIBILITY
155158
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
156159
{return !(__x == __y);}
@@ -178,6 +181,54 @@ make_exception_ptr(_Ep __e) _NOEXCEPT
178181
#endif
179182
}
180183

184+
#else // _LIBCPP_ABI_MICROSOFT
185+
186+
class _LIBCPP_TYPE_VIS exception_ptr
187+
{
188+
#if defined(__clang__)
189+
#pragma clang diagnostic push
190+
#pragma clang diagnostic ignored "-Wunused-private-field"
191+
#endif
192+
void* __ptr1_;
193+
void* __ptr2_;
194+
#if defined(__clang__)
195+
#pragma clang diagnostic pop
196+
#endif
197+
public:
198+
exception_ptr() _NOEXCEPT;
199+
exception_ptr(nullptr_t) _NOEXCEPT;
200+
exception_ptr(const exception_ptr& __other) _NOEXCEPT;
201+
exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
202+
exception_ptr& operator=(nullptr_t) _NOEXCEPT;
203+
~exception_ptr() _NOEXCEPT;
204+
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT;
205+
};
206+
207+
_LIBCPP_FUNC_VIS
208+
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;
209+
210+
inline _LIBCPP_INLINE_VISIBILITY
211+
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
212+
{return !(__x == __y);}
213+
214+
_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT;
215+
216+
_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr);
217+
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
218+
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p);
219+
220+
// This is a built-in template function which automagically extracts the required
221+
// information.
222+
template <class _E> void *__GetExceptionInfo(_E);
223+
224+
template<class _Ep>
225+
exception_ptr
226+
make_exception_ptr(_Ep __e) _NOEXCEPT
227+
{
228+
return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
229+
}
230+
231+
#endif // _LIBCPP_ABI_MICROSOFT
181232
// nested_exception
182233

183234
class _LIBCPP_EXCEPTION_ABI nested_exception

‎libcxx/lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ if (LIBCXX_TARGETING_MSVC)
121121
add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime
122122
add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime
123123
add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files
124+
add_library_flags(msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
124125
# Required for standards-complaint wide character formatting functions
125126
# (e.g. `printfw`/`scanfw`)
126127
add_library_flags(iso_stdio_wide_specifiers)

‎libcxx/src/exception.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
#if defined(_LIBCPP_ABI_MICROSOFT)
2222
#include "support/runtime/exception_msvc.ipp"
23-
#include "support/runtime/exception_pointer_unimplemented.ipp"
23+
#include "support/runtime/exception_pointer_msvc.ipp"
2424
#elif defined(_LIBCPPABI_VERSION)
2525
#include "support/runtime/exception_libcxxabi.ipp"
2626
#include "support/runtime/exception_pointer_cxxabi.ipp"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is dual licensed under the MIT and the University of Illinois Open
7+
// Source Licenses. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
14+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(_Out_ void*);
15+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*);
16+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCopy(_Out_ void*,
17+
_In_ const void*);
18+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
19+
__ExceptionPtrAssign(_Inout_ void*, _In_ const void*);
20+
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
21+
__ExceptionPtrCompare(_In_ const void*, _In_ const void*);
22+
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
23+
__ExceptionPtrToBool(_In_ const void*);
24+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrSwap(_Inout_ void*,
25+
_Inout_ void*);
26+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
27+
__ExceptionPtrCurrentException(_Out_ void*);
28+
[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
29+
__ExceptionPtrRethrow(_In_ const void*);
30+
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
31+
__ExceptionPtrCopyException(_Inout_ void*, _In_ const void*, _In_ const void*);
32+
33+
namespace std {
34+
35+
exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); }
36+
exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); }
37+
38+
exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT {
39+
__ExceptionPtrCopy(this, &__other);
40+
}
41+
exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT {
42+
__ExceptionPtrAssign(this, &__other);
43+
return *this;
44+
}
45+
46+
exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT {
47+
exception_ptr dummy;
48+
__ExceptionPtrAssign(this, &dummy);
49+
return *this;
50+
}
51+
52+
exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); }
53+
54+
exception_ptr::operator bool() const _NOEXCEPT {
55+
return __ExceptionPtrToBool(this);
56+
}
57+
58+
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
59+
return __ExceptionPtrCompare(&__x, &__y);
60+
}
61+
62+
63+
void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT {
64+
__ExceptionPtrSwap(&rhs, &lhs);
65+
}
66+
67+
exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
68+
exception_ptr __ret = nullptr;
69+
if (__ptr)
70+
__ExceptionPtrCopyException(&__ret, __except, __ptr);
71+
return __ret;
72+
}
73+
74+
exception_ptr current_exception() _NOEXCEPT {
75+
exception_ptr __ret;
76+
__ExceptionPtrCurrentException(&__ret);
77+
return __ret;
78+
}
79+
80+
_LIBCPP_NORETURN
81+
void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
82+
83+
nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {}
84+
85+
nested_exception::~nested_exception() _NOEXCEPT {}
86+
87+
_LIBCPP_NORETURN
88+
void nested_exception::rethrow_nested() const {
89+
if (__ptr_ == nullptr)
90+
terminate();
91+
rethrow_exception(__ptr_);
92+
}
93+
94+
} // namespace std

‎libcxx/test/libcxx/thread/futures/futures.promise/set_exception.pass.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
// Source Licenses. See LICENSE.TXT for details.
77
//
88
//===----------------------------------------------------------------------===//
9-
//
10-
11-
// This test depends on std::exception_ptr which has not yet been implemented.
12-
// XFAIL: LIBCXX-WINDOWS-FIXME
139

1410
// UNSUPPORTED: libcpp-no-exceptions
1511
// UNSUPPORTED: libcpp-has-no-threads

‎libcxx/test/libcxx/thread/futures/futures.promise/set_exception_at_thread_exit.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// This test depends on std::exception_ptr which has not yet been implemented.
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// UNSUPPORTED: libcpp-no-exceptions
1411
// UNSUPPORTED: libcpp-has-no-threads
1512
// UNSUPPORTED: c++98, c++03

‎libcxx/test/std/language.support/support.exception/except.nested/assign.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// <exception>
1411

1512
// class nested_exception;

‎libcxx/test/std/language.support/support.exception/except.nested/ctor_copy.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// <exception>
1411

1512
// class nested_exception;

‎libcxx/test/std/language.support/support.exception/except.nested/ctor_default.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// <exception>
1411

1512
// class nested_exception;

‎libcxx/test/std/language.support/support.exception/except.nested/rethrow_if_nested.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
10+
// UNSUPPORTED: libcpp-no-exceptions
11+
12+
// This test fails due to a stack overflow
1113
// XFAIL: LIBCXX-WINDOWS-FIXME
1214

13-
// UNSUPPORTED: libcpp-no-exceptions
1415
// <exception>
1516

1617
// class nested_exception;

‎libcxx/test/std/language.support/support.exception/except.nested/rethrow_nested.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// UNSUPPORTED: libcpp-no-exceptions
1411
// <exception>
1512

‎libcxx/test/std/language.support/support.exception/except.nested/throw_with_nested.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// UNSUPPORTED: libcpp-no-exceptions
1411
// <exception>
1512

‎libcxx/test/std/language.support/support.exception/propagation/current_exception.pass.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
10+
// This test needs to be rewritten for the Windows exception_ptr semantics
11+
// which copy the exception each time the exception_ptr is copied.
1112
// XFAIL: LIBCXX-WINDOWS-FIXME
1213

1314
// UNSUPPORTED: libcpp-no-exceptions

‎libcxx/test/std/language.support/support.exception/propagation/exception_ptr.pass.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// <exception>
1411

1512
// typedef unspecified exception_ptr;

‎libcxx/test/std/language.support/support.exception/propagation/make_exception_ptr.pass.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// UNSUPPORTED: libcpp-no-exceptions
1411
// <exception>
1512

@@ -41,7 +38,12 @@ int main()
4138
}
4239
catch (const A& a)
4340
{
41+
#ifndef _LIBCPP_ABI_MICROSOFT
4442
assert(A::constructed == 1);
43+
#else
44+
// On Windows exception_ptr copies the exception
45+
assert(A::constructed == 2);
46+
#endif
4547
assert(p != nullptr);
4648
p = nullptr;
4749
assert(p == nullptr);
@@ -50,4 +52,5 @@ int main()
5052
}
5153
assert(A::constructed == 0);
5254
}
55+
assert(A::constructed == 0);
5356
}

‎libcxx/test/std/language.support/support.exception/propagation/rethrow_exception.pass.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10-
// exception_ptr has not been implemented on Windows
11-
// XFAIL: LIBCXX-WINDOWS-FIXME
12-
1310
// UNSUPPORTED: libcpp-no-exceptions
1411
// <exception>
1512

@@ -49,7 +46,12 @@ int main()
4946
}
5047
catch (const A& a)
5148
{
49+
#ifndef _LIBCPP_ABI_MICROSOFT
5250
assert(A::constructed == 1);
51+
#else
52+
// On Windows the exception_ptr copies the exception
53+
assert(A::constructed == 2);
54+
#endif
5355
assert(p != nullptr);
5456
p = nullptr;
5557
assert(p == nullptr);
@@ -58,4 +60,5 @@ int main()
5860
}
5961
assert(A::constructed == 0);
6062
}
63+
assert(A::constructed == 0);
6164
}

0 commit comments

Comments
 (0)
Please sign in to comment.