diff --git a/include/etl/error_handler.h b/include/etl/error_handler.h index d5898fb2..8fd07c88 100644 --- a/include/etl/error_handler.h +++ b/include/etl/error_handler.h @@ -364,60 +364,6 @@ namespace etl #endif #endif -#if ETL_IS_DEBUG_BUILD - #if defined(ETL_DEBUG_USE_ASSERT_FUNCTION) - #define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} // If the condition fails, calls the assert function - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;}} // If the condition fails, calls the assert function and return - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);}} // If the condition fails, calls the assert function and return a value - - #define ETL_DEBUG_ASSERT_FAIL(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));} // Calls the assert function - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;} // Calls the assert function and return - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);} // Calls the assert function and return a value - #elif ETL_DEBUG_USING_EXCEPTIONS - #if defined(ETL_DEBUG_LOG_ERRORS) - #define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception. - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return;}} // If the condition fails, calls the error handler then throws an exception. - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return(v);}} // If the condition fails, calls the error handler then throws an exception. - - #define ETL_DEBUG_ASSERT_FAIL(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {etl::error_handler::error((e)); throw((e)); return;} // Calls the error handler then throws an exception. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); throw((e)); return(v);} // Calls the error handler then throws an exception. - #else - #define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception. - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception. - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception. - - #define ETL_DEBUG_ASSERT_FAIL(e) {throw((e));} // Throws an exception. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {throw((e));} // Throws an exception. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {throw((e));} // Throws an exception. - #endif - #elif defined(ETL_DEBUG_LOG_ERRORS) - #define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));}} // If the condition fails, calls the error handler - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return;}} // If the condition fails, calls the error handler and return - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return (v);}} // If the condition fails, calls the error handler and return a value - - #define ETL_DEBUG_ASSERT_FAIL(e) {etl::error_handler::error((e));} // Calls the error handler - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {etl::error_handler::error((e)); return;} // Calls the error handler and return - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); return (v);} // Calls the error handler and return a value - #else - #define ETL_DEBUG_ASSERT(b, e) assert((b)) // If the condition fails, asserts. - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {assert(false); return;}} // If the condition fails, asserts and return. - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {assert(false); return(v);}} // If the condition fails, asserts and return a value. - - #define ETL_DEBUG_ASSERT_FAIL(e) assert(false) // Asserts. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {assert(false); return;} // Asserts. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {assert(false); return(v);} // Asserts. - #endif -#else - #define ETL_DEBUG_ASSERT(b, e) // Does nothing. - #define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY return;} // Returns. - #define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY return(v);} // Returns a value. - - #define ETL_DEBUG_ASSERT_FAIL(e) // Does nothing. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN(e) {return;} // Returns. - #define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {return(v);} // Returns a value. -#endif - //************************************* #if defined(ETL_CHECK_PUSH_POP) #define ETL_ASSERT_CHECK_PUSH_POP(b, e) ETL_ASSERT(b, e) @@ -443,15 +389,15 @@ namespace etl //************************************* #if defined(ETL_VERBOSE_ERRORS) - #define ETL_ERROR(e) (e(__FILE__, __LINE__)) // Make an exception with the file name and line number. - #define ETL_ERROR_WITH_VALUE(e, v) (e(__FILE__, __LINE__, (v))) // Make an exception with the file name, line number and value. - #define ETL_ERROR_TEXT(verbose_text, terse_text) (verbose_text) // Use the verbose text. - #define ETL_ERROR_UNTYPED(text) (etl::exception((text),__FILE__,__LINE__)) // Make a generic exception with a message, file name and line number. + #define ETL_ERROR(e) (e(__FILE__, __LINE__)) // Make an exception with the file name and line number. + #define ETL_ERROR_WITH_VALUE(e, v) (e(__FILE__, __LINE__, (v))) // Make an exception with the file name, line number and value. + #define ETL_ERROR_TEXT(verbose_text, terse_text) (verbose_text) // Use the verbose text. + #define ETL_ERROR_GENERIC(text) (etl::exception((text),__FILE__, __LINE__)) // Make a generic exception with a message, file name and line number. #else - #define ETL_ERROR(e) (e("", __LINE__)) // Make an exception with the line number. - #define ETL_ERROR_WITH_VALUE(e, v) (e("", __LINE__, (v))) // Make an exception with the file name, line number and value. - #define ETL_ERROR_TEXT(verbose_text, terse_text) (terse_text) // Use the terse text. - #define ETL_ERROR_UNTYPED(text) (etl::exception((text),"",__LINE__)) // Make a generic exception with a message and line number. + #define ETL_ERROR(e) (e("", __LINE__)) // Make an exception with the line number. + #define ETL_ERROR_WITH_VALUE(e, v) (e("", __LINE__, (v))) // Make an exception with the file name, line number and value. + #define ETL_ERROR_TEXT(verbose_text, terse_text) (terse_text) // Use the terse text. + #define ETL_ERROR_GENERIC(text) (etl::exception((text),"", __LINE__)) // Make a generic exception with a message and line number. #endif #endif diff --git a/include/etl/expected.h b/include/etl/expected.h index 2e761348..71c9d303 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -675,7 +675,7 @@ namespace etl //******************************************* value_type* operator ->() { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR); return etl::addressof(etl::get(storage)); } @@ -685,7 +685,7 @@ namespace etl //******************************************* const value_type* operator ->() const { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR); return etl::addressof(etl::get(storage)); } @@ -695,7 +695,7 @@ namespace etl //******************************************* value_type& operator *() ETL_LVALUE_REF_QUALIFIER { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid)); return etl::get(storage); } @@ -705,7 +705,7 @@ namespace etl //******************************************* const value_type& operator *() const ETL_LVALUE_REF_QUALIFIER { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR); return etl::get(storage); } @@ -716,7 +716,7 @@ namespace etl //******************************************* value_type&& operator *()&& { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT_OR_RETURN_VALUE(has_value(), ETL_ERROR(expected_invalid), ETL_NULLPTR); return etl::move(etl::get(storage)); } @@ -726,7 +726,7 @@ namespace etl //******************************************* const value_type&& operator *() const&& { - ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid)); + ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid)); return etl::move(etl::get(storage)); } diff --git a/test/test_etl_assert.cpp b/test/test_etl_assert.cpp new file mode 100644 index 00000000..2df84d31 --- /dev/null +++ b/test/test_etl_assert.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/platform.h" +#include "etl/error_handler.h" +#include "etl/exception.h" + +namespace +{ + class TestException1 : public etl::exception + { + public: + + TestException1(string_type file_name_, numeric_type line_number_) + : exception(ETL_ERROR_TEXT("Test:error1", "1A"), file_name_, line_number_) + { + } + }; + + SUITE(test_etl_asserts) + { + TEST(test_etl_assert) + { + auto te = ETL_ERROR(TestException1); + + CHECK_EQUAL(0, strcmp(te.what(), "Test:error1")); + + CHECK_THROW(ETL_ASSERT(false, ETL_ERROR(TestException1)), TestException1); + CHECK_NO_THROW(ETL_ASSERT(true, ETL_ERROR(TestException1))); + } + + TEST(test_etl_assert_generic) + { + auto te = ETL_ERROR_GENERIC("Generic Assert Exception"); + + CHECK_EQUAL(0, strcmp(te.what(), "Generic Assert Exception")); + + CHECK_THROW(ETL_ASSERT(false, ETL_ERROR_GENERIC("Generic Assert Exception")), etl::exception); + CHECK_NO_THROW(ETL_ASSERT(true, ETL_ERROR_GENERIC("Generic Assert Exception"))); + } + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index bc0e7529..142d0136 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -10257,6 +10257,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 088c6ca8..33a5afd7 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3713,6 +3713,9 @@ Tests\Syntax Checks\Source + + Tests\Misc +