From c5a5efa9d20413bdd252746ba72b6d17df893af8 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 29 Apr 2023 03:49:41 +0800 Subject: [PATCH] ``: Fix exception specification for `optional`'s transform-construction (#3668) Co-authored-by: S. B. Tam Co-authored-by: Stephan T. Lavavej --- stl/inc/optional | 6 +++--- .../test.cpp | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index 093cbb659b..6767863110 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -85,7 +85,7 @@ struct _Optional_destruct_base { // either contains a value of _Ty or is empty ( #if _HAS_CXX23 template constexpr _Optional_destruct_base(_Construct_from_invoke_result_tag, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn, _Ux>>) + noexcept(static_cast<_Ty>(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Value(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{true} {} #endif // _HAS_CXX23 @@ -118,7 +118,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o #if _HAS_CXX23 template constexpr _Optional_destruct_base(_Construct_from_invoke_result_tag, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn, _Ux>>) + noexcept(static_cast<_Ty>(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Value(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))), _Has_value{true} {} #endif // _HAS_CXX23 @@ -277,7 +277,7 @@ public: #if _HAS_CXX23 template constexpr optional(_Construct_from_invoke_result_tag _Tag, _Fn&& _Func, _Ux&& _Arg) noexcept( - is_nothrow_constructible_v<_Ty, invoke_result_t<_Fn, _Ux>>) + noexcept(static_cast<_Ty>(_STD invoke(_STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg))))) : _Mybase(_Tag, _STD forward<_Fn>(_Func), _STD forward<_Ux>(_Arg)) {} #endif // _HAS_CXX23 diff --git a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/test.cpp b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/test.cpp index b19a121e5d..f0d38acfa0 100644 --- a/tests/std/tests/P0798R8_monadic_operations_for_std_optional/test.cpp +++ b/tests/std/tests/P0798R8_monadic_operations_for_std_optional/test.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include +#include #include #include @@ -109,7 +111,26 @@ constexpr bool test() { return true; } +template +void test_gh_3667() { + // GH-3667 : Throwing transformers will cause the program to terminate + class unique_exception : public exception {}; + + try { + optional opt(in_place); + opt.transform([](const T&) -> T { throw unique_exception{}; }); + } catch (const unique_exception&) { + return; + } catch (...) { + assert(false); // shouldn't terminate or reach here + } + assert(false); // shouldn't terminate or reach here +} + int main() { test(); static_assert(test()); + + test_gh_3667(); // trivial destructor + test_gh_3667(); // non-trivial destructor }