mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Debug assert (#1175)
* debug assert POC * Swith to ETL_CONSTEXPR14 * Finish TODO checks * First and last can be equal * Add ETL_DEBUG_THROW_EXCEPTIONS * Try allowing c++11 constexpr * Add macro for throwing from c++11 constexpr * Remove braces * Add extra asserts in size_t overload functions * Fill out debug asserts * Line up comments
This commit is contained in:
parent
cc62f212ab
commit
5b76824c61
@ -145,6 +145,8 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
reference operator[](size_t i)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return _buffer[i];
|
||||
}
|
||||
|
||||
@ -156,7 +158,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR const_reference operator[](size_t i) const
|
||||
{
|
||||
//throwing from c++11 constexpr requires a special macro
|
||||
#if ETL_USING_CPP11 && !ETL_USING_CPP14 && ETL_DEBUG_USING_EXCEPTIONS
|
||||
ETL_DEBUG_ASSERT_OR_RETURN_VALUE_CPP11_CONSTEXPR(i < SIZE, ETL_ERROR(array_out_of_range), _buffer[i]);
|
||||
#else
|
||||
ETL_DEBUG_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return _buffer[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -166,6 +175,8 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
reference front()
|
||||
{
|
||||
ETL_STATIC_ASSERT(SIZE > 0, "Array is empty.");
|
||||
|
||||
return _buffer[0];
|
||||
}
|
||||
|
||||
@ -175,6 +186,8 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR const_reference front() const
|
||||
{
|
||||
ETL_STATIC_ASSERT(SIZE > 0, "Array is empty.");
|
||||
|
||||
return _buffer[0];
|
||||
}
|
||||
|
||||
@ -185,6 +198,8 @@ namespace etl
|
||||
ETL_CONSTEXPR14
|
||||
reference back()
|
||||
{
|
||||
ETL_STATIC_ASSERT(SIZE > 0, "Array is empty.");
|
||||
|
||||
return _buffer[SIZE - 1];
|
||||
}
|
||||
|
||||
@ -194,6 +209,8 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR const_reference back() const
|
||||
{
|
||||
ETL_STATIC_ASSERT(SIZE > 0, "Array is empty.");
|
||||
|
||||
return _buffer[SIZE - 1];
|
||||
}
|
||||
|
||||
@ -429,6 +446,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
inline iterator insert_at(size_t position, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(position < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return insert(begin() + position, value);
|
||||
}
|
||||
|
||||
@ -439,6 +458,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator insert(const_iterator position, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= position && position < cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(position);
|
||||
|
||||
etl::move_backward(p, end() - 1, end());
|
||||
@ -456,6 +477,8 @@ namespace etl
|
||||
template <typename TIterator>
|
||||
inline iterator insert_at(size_t position, TIterator first, const TIterator last)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(position < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return insert(begin() + position, first, last);
|
||||
}
|
||||
|
||||
@ -468,6 +491,8 @@ namespace etl
|
||||
template <typename TIterator>
|
||||
iterator insert(const_iterator position, TIterator first, const TIterator last)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= position && position < cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(position);
|
||||
iterator result(p);
|
||||
|
||||
@ -494,6 +519,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
inline iterator erase_at(size_t position)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(position < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return erase(begin() + position);
|
||||
}
|
||||
|
||||
@ -504,6 +531,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= position && position < cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(position);
|
||||
etl::move(p + 1, end(), p);
|
||||
|
||||
@ -518,6 +547,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase_range(size_t first, size_t last)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(first <= last && last <= SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return erase(begin() + first, begin() + last);
|
||||
}
|
||||
|
||||
@ -529,6 +560,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(first);
|
||||
etl::move(last, cend(), p);
|
||||
return p;
|
||||
@ -541,6 +574,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
inline iterator erase_at(size_t position, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(position < SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return erase(begin() + position, value);
|
||||
}
|
||||
|
||||
@ -551,6 +586,8 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase(const_iterator position, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= position && position < cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(position);
|
||||
|
||||
etl::move(p + 1, end(), p);
|
||||
@ -567,16 +604,21 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase_range(size_t first, size_t last, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(first <= last && last <= SIZE, ETL_ERROR(array_out_of_range));
|
||||
|
||||
return erase(begin() + first, begin() + last, value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Erases a range of values from the array.
|
||||
///\param position The iterator to the position to erase at.
|
||||
///\param value The value to use to overwrite the last elements in the array.
|
||||
///\param first The first item to erase.
|
||||
///\param last The one past the last item to erase.
|
||||
///\param value The value to use to overwrite the last elements in the array.
|
||||
//*************************************************************************
|
||||
iterator erase(const_iterator first, const_iterator last, parameter_t value)
|
||||
{
|
||||
ETL_DEBUG_ASSERT(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(array_out_of_range));
|
||||
|
||||
iterator p = to_iterator(first);
|
||||
|
||||
p = etl::move(last, cend(), p);
|
||||
|
||||
@ -364,6 +364,62 @@ 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_VALUE_CPP11_CONSTEXPR(b, e, v) if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));} return (b) ? (v) : throw(e) // throwing from c++11 constexpr requires ? operator
|
||||
#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_VALUE_CPP11_CONSTEXPR(b, e, v) return (b) ? (v) : throw(e) // throwing from c++11 constexpr requires ? operator
|
||||
#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_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.
|
||||
|
||||
@ -675,9 +675,7 @@ namespace etl
|
||||
//*******************************************
|
||||
value_type* operator ->()
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::addressof(etl::get<value_type>(storage));
|
||||
}
|
||||
@ -687,9 +685,7 @@ namespace etl
|
||||
//*******************************************
|
||||
const value_type* operator ->() const
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::addressof(etl::get<value_type>(storage));
|
||||
}
|
||||
@ -699,9 +695,7 @@ namespace etl
|
||||
//*******************************************
|
||||
value_type& operator *() ETL_LVALUE_REF_QUALIFIER
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::get<value_type>(storage);
|
||||
}
|
||||
@ -711,9 +705,7 @@ namespace etl
|
||||
//*******************************************
|
||||
const value_type& operator *() const ETL_LVALUE_REF_QUALIFIER
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::get<value_type>(storage);
|
||||
}
|
||||
@ -724,9 +716,7 @@ namespace etl
|
||||
//*******************************************
|
||||
value_type&& operator *()&&
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::move(etl::get<value_type>(storage));
|
||||
}
|
||||
@ -736,9 +726,7 @@ namespace etl
|
||||
//*******************************************
|
||||
const value_type&& operator *() const&&
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
#endif
|
||||
ETL_DEBUG_ASSERT(has_value(), ETL_ERROR(expected_invalid));
|
||||
|
||||
return etl::move(etl::get<value_type>(storage));
|
||||
}
|
||||
|
||||
@ -251,6 +251,16 @@ SOFTWARE.
|
||||
#define ETL_NOT_USING_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
//*************************************
|
||||
// Indicate if C++ exceptions are enabled for debug asserts.
|
||||
#if ETL_IS_DEBUG_BUILD && defined(ETL_DEBUG_THROW_EXCEPTIONS)
|
||||
#define ETL_DEBUG_USING_EXCEPTIONS 1
|
||||
#define ETL_DEBUG_NOT_USING_EXCEPTIONS 0
|
||||
#else
|
||||
#define ETL_DEBUG_USING_EXCEPTIONS 0
|
||||
#define ETL_DEBUG_NOT_USING_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
//*************************************
|
||||
// Indicate if nullptr is used.
|
||||
#if ETL_NO_NULLPTR_SUPPORT
|
||||
|
||||
@ -31,7 +31,9 @@ SOFTWARE.
|
||||
#ifndef ETL_PROFILE_H_INCLUDED
|
||||
#define ETL_PROFILE_H_INCLUDED
|
||||
|
||||
#define ETL_DEBUG
|
||||
#define ETL_THROW_EXCEPTIONS
|
||||
#define ETL_DEBUG_THROW_EXCEPTIONS
|
||||
#define ETL_VERBOSE_ERRORS
|
||||
#define ETL_CHECK_PUSH_POP
|
||||
#define ETL_ISTRING_REPAIR_ENABLE
|
||||
|
||||
@ -134,6 +134,9 @@ namespace
|
||||
{
|
||||
CHECK_EQUAL(data[i], compare_data[i]);
|
||||
}
|
||||
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
CHECK_THROW({ int d = data[data.size()]; (void)d; }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -145,6 +148,9 @@ namespace
|
||||
{
|
||||
CHECK_EQUAL(data[i], compare_data[i]);
|
||||
}
|
||||
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
CHECK_THROW({ int d = data[data.size()]; (void)d; }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -443,6 +449,10 @@ namespace
|
||||
CHECK_EQUAL(data[9], *result);
|
||||
isEqual = std::equal(data.begin(), data.end(), std::begin(check3));
|
||||
CHECK(isEqual);
|
||||
|
||||
// Insert out of range
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
CHECK_THROW({ result = data.insert_at(data.size(), 99); }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -493,6 +503,10 @@ namespace
|
||||
CHECK_EQUAL(data[4], *result);
|
||||
isEqual = std::equal(data.begin(), data.end(), std::begin(check5));
|
||||
CHECK(isEqual);
|
||||
|
||||
// Insert out of range
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
CHECK_THROW({ result = data.insert_at(data.size(), &source2[0], &source2[13]); }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -547,6 +561,10 @@ namespace
|
||||
CHECK_EQUAL(data[9], *result);
|
||||
isEqual = std::equal(data.begin(), data.end(), std::begin(check3b));
|
||||
CHECK(isEqual);
|
||||
|
||||
// Erase out of range
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
CHECK_THROW({ result = data.erase_at(data.size()); }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -601,6 +619,13 @@ namespace
|
||||
CHECK_EQUAL(data[5], *result);
|
||||
isEqual = std::equal(data.begin(), data.end(), std::begin(check3b));
|
||||
CHECK(isEqual);
|
||||
|
||||
//ETL_DEBUG and ETL_THROW_EXCEPTIONS are defined
|
||||
// first is greater than last
|
||||
CHECK_THROW({ result = data.erase_range(6, 5, 99); }, etl::array_out_of_range);
|
||||
|
||||
// Erase out of range
|
||||
CHECK_THROW({ result = data.erase_range(5, data.size() + 1, 99); }, etl::array_out_of_range);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user