From 8ee74d8e0ba2291c2cc8b2d5e28d2ffa4f50717c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 24 Nov 2024 20:16:40 +0100 Subject: [PATCH] P3068R6 Allowing exception throwing in constant-evaluation --- source/expressions.tex | 20 ++++++--- source/preprocessor.tex | 1 + source/support.tex | 92 ++++++++++++++++++++++------------------- 3 files changed, 65 insertions(+), 48 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 10b6eee056..61e4a21ff5 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -7878,6 +7878,13 @@ unless it deallocates a region of storage allocated within the evaluation of $E$; +\item +a construction of an exception object, +unless the exception object and +all of its implicit copies created by invocations of +\tcode{std::current_exception} or \tcode{std::rethrow_exception}\iref{propagation} +are destroyed within the evaluation of $E$; + \item an \grammarterm{await-expression}\iref{expr.await}; @@ -7889,15 +7896,18 @@ relational\iref{expr.rel}, or equality\iref{expr.eq} operator where the result is unspecified; -\item -a \grammarterm{throw-expression}\iref{expr.throw}; - \item a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression on a glvalue that refers to an object -whose dynamic type is constexpr-unknown or -that would throw an exception; +whose dynamic type is constexpr-unknown; + +\item +a \tcode{dynamic_cast}\iref{expr.dynamic.cast} expression, +\tcode{typeid}\iref{expr.typeid} expression, or +\tcode{new-expression}\iref{expr.new} +that would throw an exception +where no definition of the exception type is reachable; \item an \grammarterm{asm-declaration}\iref{dcl.asm}; diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 81b87b4626..b1676c5ebd 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1859,6 +1859,7 @@ \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep \defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_constexpr_exceptions} & \tcode{202411L} \\ \rowsep \defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep \defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep \defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep diff --git a/source/support.tex b/source/support.tex index 28c15ac913..6082f14a0b 100644 --- a/source/support.tex +++ b/source/support.tex @@ -607,6 +607,7 @@ #define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202306L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 202306L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_exceptions}@ 202411L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // freestanding, also in \libheader{memory} @@ -2941,7 +2942,7 @@ class bad_alloc : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2954,7 +2955,7 @@ \indexlibrarymember{what}{bad_alloc}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -2972,7 +2973,7 @@ class bad_array_new_length : public bad_alloc { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2985,7 +2986,7 @@ \indexlibrarymember{what}{bad_array_new_length}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3310,7 +3311,7 @@ class bad_cast : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3326,7 +3327,7 @@ \indexlibrarymember{what}{bad_cast}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3344,7 +3345,7 @@ class bad_typeid : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3360,7 +3361,7 @@ \indexlibrarymember{what}{bad_typeid}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3775,16 +3776,16 @@ terminate_handler set_terminate(terminate_handler f) noexcept; [[noreturn]] void terminate() noexcept; - int uncaught_exceptions() noexcept; + constexpr int uncaught_exceptions() noexcept; using exception_ptr = @\unspec@; - exception_ptr current_exception() noexcept; - [[noreturn]] void rethrow_exception(exception_ptr p); - template exception_ptr make_exception_ptr(E e) noexcept; + constexpr exception_ptr current_exception() noexcept; + [[noreturn]] constexpr void rethrow_exception(exception_ptr p); + template constexpr exception_ptr make_exception_ptr(E e) noexcept; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -3796,11 +3797,11 @@ namespace std { class exception { public: - exception() noexcept; - exception(const exception&) noexcept; - exception& operator=(const exception&) noexcept; - virtual ~exception(); - virtual const char* what() const noexcept; + constexpr exception() noexcept; + constexpr exception(const exception&) noexcept; + constexpr exception& operator=(const exception&) noexcept; + constexpr virtual ~exception(); + constexpr virtual const char* what() const noexcept; }; } \end{codeblock} @@ -3833,8 +3834,8 @@ \indexlibraryctor{exception}% \indexlibrarymember{operator=}{exception}% \begin{itemdecl} -exception(const exception& rhs) noexcept; -exception& operator=(const exception& rhs) noexcept; +constexpr exception(const exception& rhs) noexcept; +constexpr exception& operator=(const exception& rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3846,7 +3847,7 @@ \indexlibrarydtor{exception}% \begin{itemdecl} -virtual ~exception(); +constexpr virtual ~exception(); \end{itemdecl} \begin{itemdescr} @@ -3858,13 +3859,15 @@ \indexlibrarymember{what}{exception}% \begin{itemdecl} -virtual const char* what() const noexcept; +constexpr virtual const char* what() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -An \impldef{return value of \tcode{exception::what}} \ntbs{}. +An \impldef{return value of \tcode{exception::what}} \ntbs{}, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \pnum \remarks @@ -3885,7 +3888,7 @@ class bad_exception : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3900,7 +3903,7 @@ \indexlibrarymember{what}{bad_exception}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -4007,7 +4010,7 @@ \indexlibraryglobal{uncaught_exceptions}% \begin{itemdecl} -int uncaught_exceptions() noexcept; +constexpr int uncaught_exceptions() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4068,11 +4071,14 @@ Changes in the number of \tcode{exception_ptr} objects that refer to a particular exception do not introduce a data race. \end{note} + +\pnum +All member functions are marked \tcode{constexpr}. \end{itemdescr} \indexlibraryglobal{current_exception}% \begin{itemdecl} -exception_ptr current_exception() noexcept; +constexpr exception_ptr current_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4103,7 +4109,7 @@ \indexlibraryglobal{rethrow_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_exception(exception_ptr p); +[[noreturn]] constexpr void rethrow_exception(exception_ptr p); \end{itemdecl} \begin{itemdescr} @@ -4131,7 +4137,7 @@ \indexlibraryglobal{make_exception_ptr}% \begin{itemdecl} -template exception_ptr make_exception_ptr(E e) noexcept; +template constexpr exception_ptr make_exception_ptr(E e) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4160,18 +4166,18 @@ namespace std { class nested_exception { public: - nested_exception() noexcept; - nested_exception(const nested_exception&) noexcept = default; - nested_exception& operator=(const nested_exception&) noexcept = default; - virtual ~nested_exception() = default; + constexpr nested_exception() noexcept; + constexpr nested_exception(const nested_exception&) noexcept = default; + constexpr nested_exception& operator=(const nested_exception&) noexcept = default; + constexpr virtual ~nested_exception() = default; // access functions - [[noreturn]] void rethrow_nested() const; - exception_ptr nested_ptr() const noexcept; + [[noreturn]] constexpr void rethrow_nested() const; + constexpr exception_ptr nested_ptr() const noexcept; }; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -4188,7 +4194,7 @@ \indexlibraryctor{nested_exception}% \begin{itemdecl} -nested_exception() noexcept; +constexpr nested_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4199,7 +4205,7 @@ \indexlibrarymember{rethrow_nested}{nested_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_nested() const; +[[noreturn]] constexpr void rethrow_nested() const; \end{itemdecl} \begin{itemdescr} @@ -4211,7 +4217,7 @@ \indexlibrarymember{nested_ptr}{nested_exception}% \begin{itemdecl} -exception_ptr nested_ptr() const noexcept; +constexpr exception_ptr nested_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4222,7 +4228,7 @@ \indexlibrarymember{throw_with_nested}{nested_exception}% \begin{itemdecl} -template [[noreturn]] void throw_with_nested(T&& t); +template [[noreturn]] constexpr void throw_with_nested(T&& t); \end{itemdecl} \begin{itemdescr} @@ -4245,7 +4251,7 @@ \indexlibrarymember{rethrow_if_nested}{nested_exception}% \begin{itemdecl} -template void rethrow_if_nested(const E& e); +template constexpr void rethrow_if_nested(const E& e); \end{itemdecl} \begin{itemdescr}