diff --git a/sycl/include/CL/sycl/exception.hpp b/sycl/include/CL/sycl/exception.hpp index 0b6d3cee5e128..7854231150cb2 100644 --- a/sycl/include/CL/sycl/exception.hpp +++ b/sycl/include/CL/sycl/exception.hpp @@ -28,13 +28,29 @@ class context; /// \ingroup sycl_api class __SYCL_EXPORT exception : public std::exception { public: + __SYCL2020_DEPRECATED("The version of an exception constructor which takes " + "no arguments is deprecated.") exception() = default; - exception(std::error_code, const char *Msg) - : exception(Msg, PI_INVALID_VALUE) {} + exception(std::error_code, const char *Msg); - exception(std::error_code, const std::string &Msg) - : exception(Msg, PI_INVALID_VALUE) {} + exception(std::error_code, const std::string &Msg); + + // new SYCL 2020 constructors + exception(std::error_code); + exception(int, const std::error_category &, const std::string &); + exception(int, const std::error_category &, const char *); + exception(int, const std::error_category &); + + exception(context, std::error_code, const std::string &); + exception(context, std::error_code, const char *); + exception(context, std::error_code); + exception(context, int, const std::error_category &, const std::string &); + exception(context, int, const std::error_category &, const char *); + exception(context, int, const std::error_category &); + + const std::error_code &code() const noexcept; + const std::error_category &category() const noexcept; const char *what() const noexcept final; @@ -42,6 +58,7 @@ class __SYCL_EXPORT exception : public std::exception { context get_context() const; + __SYCL2020_DEPRECATED("use sycl::exception.code() instead.") cl_int get_cl_code() const; private: @@ -59,10 +76,18 @@ class __SYCL_EXPORT exception : public std::exception { : MMsg(Msg + " " + detail::codeToString(CLErr)), MCLErr(CLErr), MContext(Context) {} - exception(const std::string &Msg) : MMsg(Msg), MContext(nullptr) {} + exception(const string_class &Msg) : MMsg(Msg), MContext(nullptr) {} + + // base constructor for all SYCL 2020 constructors + // exception(context *ctxPtr, std::error_code ec, const std::string + // &what_arg); + exception(std::error_code ec, std::shared_ptr SharedPtrCtx, + const std::string &what_arg); }; -class runtime_error : public exception { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::runtime instead.") runtime_error + : public exception { public: runtime_error() = default; @@ -71,22 +96,34 @@ class runtime_error : public exception { runtime_error(const std::string &Msg, cl_int Err) : exception(Msg, Err) {} }; -class kernel_error : public runtime_error { +class __SYCL2020_DEPRECATED("use sycl::exception with sycl::errc::kernel or " + "errc::kernel_argument instead.") kernel_error + : public runtime_error { using runtime_error::runtime_error; }; -class accessor_error : public runtime_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::accessor instead.") accessor_error + : public runtime_error { using runtime_error::runtime_error; }; -class nd_range_error : public runtime_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::nd_range instead.") nd_range_error + : public runtime_error { using runtime_error::runtime_error; }; -class event_error : public runtime_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::event instead.") event_error + : public runtime_error { using runtime_error::runtime_error; }; -class invalid_parameter_error : public runtime_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with a sycl::errc enum value instead.") + invalid_parameter_error : public runtime_error { using runtime_error::runtime_error; }; -class device_error : public exception { +class __SYCL2020_DEPRECATED( + "use sycl::exception with a sycl::errc enum value instead.") device_error + : public exception { public: device_error() = default; @@ -95,25 +132,39 @@ class device_error : public exception { device_error(const std::string &Msg, cl_int Err) : exception(Msg, Err) {} }; -class compile_program_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with a sycl::errc enum value instead.") + compile_program_error : public device_error { using device_error::device_error; }; -class link_program_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with a sycl::errc enum value instead.") + link_program_error : public device_error { using device_error::device_error; }; -class invalid_object_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with a sycl::errc enum value instead.") + invalid_object_error : public device_error { using device_error::device_error; }; -class memory_allocation_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::memory_allocation instead.") + memory_allocation_error : public device_error { using device_error::device_error; }; -class platform_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::platform instead.") platform_error + : public device_error { using device_error::device_error; }; -class profiling_error : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::profiling instead.") profiling_error + : public device_error { using device_error::device_error; }; -class feature_not_supported : public device_error { +class __SYCL2020_DEPRECATED( + "use sycl::exception with sycl::errc::feature_not_supported instead.") + feature_not_supported : public device_error { using device_error::device_error; }; diff --git a/sycl/source/exception.cpp b/sycl/source/exception.cpp index 75de7c5dd577f..aeeda10dbaec1 100644 --- a/sycl/source/exception.cpp +++ b/sycl/source/exception.cpp @@ -10,9 +10,96 @@ #include #include +#include + __SYCL_INLINE_NAMESPACE(cl) { namespace sycl { +namespace { // anonymous +constexpr char ReservedForErrorcode[] = + "01234567812345678"; // 17 (string terminator plus error code) +std::error_code SYCL121ProxyErrorcode = make_error_code(sycl::errc::invalid); +} // namespace + +exception::exception(std::error_code EC, const char *Msg) + : exception(EC, nullptr, Msg) {} + +exception::exception(std::error_code EC, const std::string &Msg) + : exception(EC, nullptr, Msg) {} + +// new SYCL 2020 constructors +exception::exception(std::error_code EC) : exception(EC, nullptr, "") {} + +exception::exception(int EV, const std::error_category &ECat, + const std::string &WhatArg) + : exception({EV, ECat}, nullptr, WhatArg) {} + +exception::exception(int EV, const std::error_category &ECat, + const char *WhatArg) + : exception({EV, ECat}, nullptr, std::string(WhatArg)) {} + +exception::exception(int EV, const std::error_category &ECat) + : exception({EV, ECat}, nullptr, "") {} + +exception::exception(context Ctx, std::error_code EC, + const std::string &WhatArg) + : exception(EC, std::make_shared(Ctx), WhatArg) {} + +exception::exception(context Ctx, std::error_code EC, const char *WhatArg) + : exception(Ctx, EC, std::string(WhatArg)) {} + +exception::exception(context Ctx, std::error_code EC) + : exception(Ctx, EC, "") {} + +exception::exception(context Ctx, int EV, const std::error_category &ECat, + const char *WhatArg) + : exception(Ctx, {EV, ECat}, std::string(WhatArg)) {} + +exception::exception(context Ctx, int EV, const std::error_category &ECat, + const std::string &WhatArg) + : exception(Ctx, {EV, ECat}, WhatArg) {} + +exception::exception(context Ctx, int EV, const std::error_category &ECat) + : exception(Ctx, EV, 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), MCLErr(PI_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]; + ReservedPtr[0] = '\0'; + ReservedPtr++; + // insert error code + std::error_code *ECPtr = reinterpret_cast(ReservedPtr); + memcpy(ECPtr, &EC, sizeof(std::error_code)); +} + +const std::error_code &exception::code() const noexcept { + const char *WhatStr = MMsg.c_str(); + // advance to inner string-terminator + int StringTermPoint = MMsg.length() - strlen(ReservedForErrorcode); + if (StringTermPoint >= 0) { + const char *ReservedPtr = &WhatStr[StringTermPoint]; + // check for string terminator, which denotes a SYCL 2020 exception + if (ReservedPtr[0] == '\0') { + ReservedPtr++; + const std::error_code *ECPtr = + reinterpret_cast(ReservedPtr); + return *ECPtr; + } + } + // else the exception originates from some SYCL 1.2.1 source + return SYCL121ProxyErrorcode; +} + +const std::error_category &exception::category() const noexcept { + return code().category(); +} + const char *exception::what() const noexcept { return MMsg.c_str(); } bool exception::has_context() const { return (MContext != nullptr); } diff --git a/sycl/test/abi/sycl_symbols_linux.dump b/sycl/test/abi/sycl_symbols_linux.dump index 0683df8dcc193..fb694a11dac2d 100644 --- a/sycl/test/abi/sycl_symbols_linux.dump +++ b/sycl/test/abi/sycl_symbols_linux.dump @@ -3928,6 +3928,32 @@ _ZN2cl4sycl8platformC1Ev _ZN2cl4sycl8platformC2EP15_cl_platform_id _ZN2cl4sycl8platformC2ERKNS0_15device_selectorE _ZN2cl4sycl8platformC2Ev +_ZN2cl4sycl9exceptionC1ENS0_7contextESt10error_code +_ZN2cl4sycl9exceptionC1ENS0_7contextESt10error_codePKc +_ZN2cl4sycl9exceptionC1ENS0_7contextESt10error_codeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC1ENS0_7contextEiRKNSt3_V214error_categoryE +_ZN2cl4sycl9exceptionC1ENS0_7contextEiRKNSt3_V214error_categoryEPKc +_ZN2cl4sycl9exceptionC1ENS0_7contextEiRKNSt3_V214error_categoryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC1ESt10error_code +_ZN2cl4sycl9exceptionC1ESt10error_codePKc +_ZN2cl4sycl9exceptionC1ESt10error_codeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC1ESt10error_codeSt10shared_ptrINS0_7contextEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC1EiRKNSt3_V214error_categoryE +_ZN2cl4sycl9exceptionC1EiRKNSt3_V214error_categoryEPKc +_ZN2cl4sycl9exceptionC1EiRKNSt3_V214error_categoryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC2ENS0_7contextESt10error_code +_ZN2cl4sycl9exceptionC2ENS0_7contextESt10error_codePKc +_ZN2cl4sycl9exceptionC2ENS0_7contextESt10error_codeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC2ENS0_7contextEiRKNSt3_V214error_categoryE +_ZN2cl4sycl9exceptionC2ENS0_7contextEiRKNSt3_V214error_categoryEPKc +_ZN2cl4sycl9exceptionC2ENS0_7contextEiRKNSt3_V214error_categoryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC2ESt10error_code +_ZN2cl4sycl9exceptionC2ESt10error_codePKc +_ZN2cl4sycl9exceptionC2ESt10error_codeRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC2ESt10error_codeSt10shared_ptrINS0_7contextEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE +_ZN2cl4sycl9exceptionC2EiRKNSt3_V214error_categoryE +_ZN2cl4sycl9exceptionC2EiRKNSt3_V214error_categoryEPKc +_ZN2cl4sycl9exceptionC2EiRKNSt3_V214error_categoryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE _ZN2cl4sycl9kernel_idC1EPKc _ZN2cl4sycl9kernel_idC2EPKc _ZNK2cl4sycl12cpu_selectorclERKNS0_6deviceE @@ -4284,7 +4310,9 @@ _ZNK2cl4sycl8platform9getNativeEv _ZNK2cl4sycl9exception11get_cl_codeEv _ZNK2cl4sycl9exception11get_contextEv _ZNK2cl4sycl9exception11has_contextEv +_ZNK2cl4sycl9exception4codeEv _ZNK2cl4sycl9exception4whatEv +_ZNK2cl4sycl9exception8categoryEv _ZNK2cl4sycl9kernel_id8get_nameEv __sycl_register_lib __sycl_unregister_lib diff --git a/sycl/test/basic_tests/exceptions-SYCL-2020.cpp b/sycl/test/basic_tests/exceptions-SYCL-2020.cpp new file mode 100644 index 0000000000000..f20320106a183 --- /dev/null +++ b/sycl/test/basic_tests/exceptions-SYCL-2020.cpp @@ -0,0 +1,77 @@ +// RUN: %clangxx -fsycl %s -o %t.out +// RUN: %RUN_ON_HOST %t.out + +#include + +using namespace cl::sycl; + +int main() { + // Test new constructors, initially each with empty string messages. + std::string emptyStr; + const char *emptyCharPtr = ""; + + // Going to set the error code values to each of the enum (0-12). + exception ex1(make_error_code(errc::runtime), emptyStr); + exception ex2(make_error_code(errc::kernel), emptyCharPtr); + exception ex3(make_error_code(errc::accessor)); + exception ex4(static_cast(errc::nd_range), sycl_category(), emptyStr); + exception ex5(static_cast(errc::event), sycl_category(), emptyCharPtr); + exception ex6(static_cast(errc::kernel_argument), sycl_category()); + + queue Q; + context ctx = Q.get_context(); + exception ex7(ctx, make_error_code(errc::build), emptyStr); + exception ex8(ctx, make_error_code(errc::invalid), emptyCharPtr); + exception ex9(ctx, make_error_code(errc::memory_allocation)); + exception ex10(ctx, static_cast(errc::platform), sycl_category(), + emptyStr); + exception ex11(ctx, static_cast(errc::profiling), sycl_category(), + emptyCharPtr); + exception ex12(ctx, static_cast(errc::feature_not_supported), + sycl_category()); + + std::vector v{ex1, ex2, ex3, ex4, ex5, ex6, + ex7, ex8, ex9, ex10, ex11, ex12}; + for (int i = 0; i < 12; i++) { + exception ex = v[i]; + assert(ex.code().value() == i && "unexpected error_code.value() retrieved"); + assert(ex.category() == sycl_category() && "expected SYCL error category"); + if (i < 6) { + assert(!ex.has_context() && + "none of the first six exceptions should have a context"); + } else { + assert(ex.has_context() && ex.get_context() == ctx && + "the second six exceptions should have a context equal to ctx"); + } + assert(strlen(ex.what()) == 0 && + "all these exceptions were initialized with empty strings. We " + "should not have anything in the 'what' message"); + } + + // Now test constructor with a real string value, including one containing + // null string terminator + std::string testString("this is a test"); + exception ex_string1(make_error_code(errc::kernel_not_supported), testString); + assert(testString.compare(ex_string1.what()) == 0); + testString[0] = '\0'; + exception ex_early_terminated(make_error_code(errc::kernel_not_supported), + testString); + assert(ex_early_terminated.code().value() == + static_cast(errc::kernel_not_supported)); + char testCharPtr[] = "this is also a test"; + exception ex_string2(make_error_code(errc::backend_mismatch), testCharPtr); + assert(strcmp(ex_string2.what(), testCharPtr) == 0); + + // Test sycl_category. + assert(std::string("SYCL").compare(sycl_category().name()) == 0 && + "sycl_category name should be SYCL"); + + // Test make_error_code. + std::error_code ec = make_error_code(errc::feature_not_supported); + assert(ec.value() == static_cast(errc::feature_not_supported)); + assert(std::string("SYCL").compare(ec.category().name()) == 0 && + "error code category name should be SYCL"); + + std::cout << "OK" << std::endl; + return 0; +} diff --git a/sycl/test/warnings/sycl_2020_deprecations.cpp b/sycl/test/warnings/sycl_2020_deprecations.cpp index f75fe85874f3c..8ebe89264fd5a 100644 --- a/sycl/test/warnings/sycl_2020_deprecations.cpp +++ b/sycl/test/warnings/sycl_2020_deprecations.cpp @@ -68,12 +68,45 @@ int main() { size_t BufferGetCount = Buffer.get_count(); size_t BufferSize = Buffer.size(); + // expected-warning@+1 {{'runtime_error' is deprecated: use sycl::exception with sycl::errc::runtime instead.}} + sycl::runtime_error re; + // expected-warning@+1 {{'kernel_error' is deprecated: use sycl::exception with sycl::errc::kernel or errc::kernel_argument instead.}} + sycl::kernel_error ke; + // expected-warning@+1 {{'accessor_error' is deprecated: use sycl::exception with sycl::errc::accessor instead.}} + sycl::accessor_error ae; + // expected-warning@+1 {{'nd_range_error' is deprecated: use sycl::exception with sycl::errc::nd_range instead.}} + sycl::nd_range_error ne; + // expected-warning@+1 {{'event_error' is deprecated: use sycl::exception with sycl::errc::event instead.}} + sycl::event_error ee; + // expected-warning@+1 {{'invalid_parameter_error' is deprecated: use sycl::exception with a sycl::errc enum value instead.}} + sycl::invalid_parameter_error ipe; + // expected-warning@+1 {{'device_error' is deprecated: use sycl::exception with a sycl::errc enum value instead.}} + sycl::device_error de; + // expected-warning@+1 {{'compile_program_error' is deprecated: use sycl::exception with a sycl::errc enum value instead.}} + sycl::compile_program_error cpe; + // expected-warning@+1 {{'link_program_error' is deprecated: use sycl::exception with a sycl::errc enum value instead.}} + sycl::link_program_error lpe; + // expected-warning@+1 {{'invalid_object_error' is deprecated: use sycl::exception with a sycl::errc enum value instead.}} + sycl::invalid_object_error ioe; + // expected-warning@+1 {{'memory_allocation_error' is deprecated: use sycl::exception with sycl::errc::memory_allocation instead.}} + sycl::memory_allocation_error mae; + // expected-warning@+1 {{'platform_error' is deprecated: use sycl::exception with sycl::errc::platform instead.}} + sycl::platform_error ple; + // expected-warning@+1 {{'profiling_error' is deprecated: use sycl::exception with sycl::errc::profiling instead.}} + sycl::profiling_error pre; + // expected-warning@+1 {{'feature_not_supported' is deprecated: use sycl::exception with sycl::errc::feature_not_supported instead.}} + sycl::feature_not_supported fns; // expected-warning@+1{{'string_class' is deprecated: use STL classes directly}} sycl::string_class Str = "abc"; (void)Str; // expected-warning@+1{{'mutex_class' is deprecated: use STL classes directly}} sycl::mutex_class Mtx; (void)Mtx; + // expected-warning@+1{{'exception' is deprecated: The version of an exception constructor which takes no arguments is deprecated.}} + sycl::exception ex; + // expected-warning@+1{{'get_cl_code' is deprecated: use sycl::exception.code() instead.}} + ex.get_cl_code(); + (void)ex; Queue.submit([](sycl::handler &CGH) { // expected-warning@+3{{'nd_range' is deprecated: offsets are deprecated in SYCL2020}}