From 659c982ed4c39e04a2ffeb8e37f4225a46acdf85 Mon Sep 17 00:00:00 2001 From: "Larsen, Steffen" Date: Thu, 11 Aug 2022 11:12:09 -0700 Subject: [PATCH 1/2] [SYCL] Make sycl::exception nothrow copy constructible Due to std::string not being nothrow copy constructible, neither is sycl::exception. As a throw in the copy constructor when throwing an exception will cause a termination of the program, sycl::exception should never be able to throw. These changes make sycl::exception nothrow copy constructible by making its std::string member a shared pointer. Signed-off-by: Larsen, Steffen --- sycl/include/sycl/exception.hpp | 10 ++++++---- sycl/source/exception.cpp | 14 +++++++------- .../exception_nothrow_copy_constructible.cpp | 11 +++++++++++ 3 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 sycl/test/regression/exception_nothrow_copy_constructible.cpp diff --git a/sycl/include/sycl/exception.hpp b/sycl/include/sycl/exception.hpp index 3d4c3b66a83e..812adb23eb40 100644 --- a/sycl/include/sycl/exception.hpp +++ b/sycl/include/sycl/exception.hpp @@ -97,7 +97,7 @@ class __SYCL_EXPORT exception : public std::exception { cl_int get_cl_code() const; private: - std::string MMsg; + std::shared_ptr MMsg; pi_int32 MPIErr; std::shared_ptr MContext; @@ -108,8 +108,9 @@ class __SYCL_EXPORT exception : public std::exception { : exception(std::string(Msg), PIErr, Context) {} exception(const std::string &Msg, const pi_int32 PIErr, std::shared_ptr Context = nullptr) - : MMsg(Msg + " " + detail::codeToString(PIErr)), MPIErr(PIErr), - MContext(Context) {} + : MMsg(std::make_shared(Msg + " " + + detail::codeToString(PIErr))), + MPIErr(PIErr), MContext(Context) {} // base constructors used by SYCL 1.2.1 exception subclasses exception(std::error_code ec, const char *Msg, const pi_int32 PIErr, @@ -122,7 +123,8 @@ class __SYCL_EXPORT exception : public std::exception { MPIErr = PIErr; } - exception(const std::string &Msg) : MMsg(Msg), MContext(nullptr) {} + exception(const std::string &Msg) + : MMsg(std::make_shared(Msg)), MContext(nullptr) {} // base constructor for all SYCL 2020 constructors // exception(context *ctxPtr, std::error_code ec, const std::string diff --git a/sycl/source/exception.cpp b/sycl/source/exception.cpp index 3394e2f6b414..13c37623c4f4 100644 --- a/sycl/source/exception.cpp +++ b/sycl/source/exception.cpp @@ -65,12 +65,12 @@ exception::exception(context Ctx, int EV, const std::error_category &ECat) // protected base constructor for all SYCL 2020 constructors exception::exception(std::error_code EC, std::shared_ptr SharedPtrCtx, const std::string &WhatArg) - : MMsg(WhatArg + ReservedForErrorcode), MPIErr(PI_ERROR_INVALID_VALUE), - MContext(SharedPtrCtx) { + : MMsg(std::make_shared(WhatArg + ReservedForErrorcode)), + MPIErr(PI_ERROR_INVALID_VALUE), MContext(SharedPtrCtx) { // For compatibility with previous implementation, we are "hiding" the // std::error_code in the MMsg string, behind the null string terminator - const int StringTermPoint = MMsg.length() - strlen(ReservedForErrorcode); - char *ReservedPtr = &MMsg[StringTermPoint]; + const int StringTermPoint = MMsg->length() - strlen(ReservedForErrorcode); + char *ReservedPtr = &(*MMsg)[StringTermPoint]; ReservedPtr[0] = '\0'; ReservedPtr++; // insert error code @@ -79,9 +79,9 @@ exception::exception(std::error_code EC, std::shared_ptr SharedPtrCtx, } const std::error_code &exception::code() const noexcept { - const char *WhatStr = MMsg.c_str(); + const char *WhatStr = MMsg->c_str(); // advance to inner string-terminator - int StringTermPoint = MMsg.length() - strlen(ReservedForErrorcode); + int StringTermPoint = MMsg->length() - strlen(ReservedForErrorcode); if (StringTermPoint >= 0) { const char *ReservedPtr = &WhatStr[StringTermPoint]; // check for string terminator, which denotes a SYCL 2020 exception @@ -100,7 +100,7 @@ const std::error_category &exception::category() const noexcept { return code().category(); } -const char *exception::what() const noexcept { return MMsg.c_str(); } +const char *exception::what() const noexcept { return MMsg->c_str(); } bool exception::has_context() const { return (MContext != nullptr); } diff --git a/sycl/test/regression/exception_nothrow_copy_constructible.cpp b/sycl/test/regression/exception_nothrow_copy_constructible.cpp new file mode 100644 index 000000000000..5aa264b6aaee --- /dev/null +++ b/sycl/test/regression/exception_nothrow_copy_constructible.cpp @@ -0,0 +1,11 @@ +// RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify %s +// expected-no-diagnostics + +#include +#include + +int main() { + static_assert(std::is_nothrow_copy_constructible_v, + "sycl::exception is not nothrow copy constructible."); + return 0; +} From 22ff65a9355cc4dcec16ef00a6196113edc448a3 Mon Sep 17 00:00:00 2001 From: Steffen Larsen Date: Fri, 12 Aug 2022 09:27:21 +0100 Subject: [PATCH 2/2] Update sycl/include/sycl/exception.hpp Co-authored-by: aelovikov-intel --- sycl/include/sycl/exception.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sycl/include/sycl/exception.hpp b/sycl/include/sycl/exception.hpp index 812adb23eb40..0607312a0172 100644 --- a/sycl/include/sycl/exception.hpp +++ b/sycl/include/sycl/exception.hpp @@ -97,6 +97,8 @@ class __SYCL_EXPORT exception : public std::exception { cl_int get_cl_code() const; private: + // Exceptions must be noexcept copy constructible, so cannot use std::string + // directly. std::shared_ptr MMsg; pi_int32 MPIErr; std::shared_ptr MContext;