/* * This file is part of the DXX-Rebirth project . * It is copyright by its individual contributors, as recorded in the * project's Git history. See COPYING.txt at the top level for license * terms and a link to the Git history. */ #pragma once #include #include #include #include "fwd-valptridx.h" #include "compiler-array.h" #include "pack.h" #include "compiler-poison.h" #ifdef DXX_CONSTANT_TRUE #define DXX_VALPTRIDX_STATIC_CHECK(SUCCESS_CONDITION,FAILURE_FUNCTION,FAILURE_STRING) \ static_cast(DXX_CONSTANT_TRUE(!SUCCESS_CONDITION) && \ (DXX_ALWAYS_ERROR_FUNCTION(FAILURE_FUNCTION, FAILURE_STRING), 0) \ ) \ #ifdef DXX_HAVE_ATTRIBUTE_WARNING /* This causes many warnings because some conversions are not checked for * safety. Eliminating the warnings by changing the call sites to check first * would be a useful improvement. */ //#define DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT __attribute__((__warning__("call not eliminated"))) #endif #else #define DXX_VALPTRIDX_STATIC_CHECK(E,F,S) #endif #define DXX_VALPTRIDX_CHECK(SUCCESS_CONDITION,ERROR,FAILURE_STRING,...) \ ( DXX_BEGIN_COMPOUND_STATEMENT { \ const bool dxx_valptridx_check_success_condition = (SUCCESS_CONDITION); \ DXX_VALPTRIDX_STATIC_CHECK(dxx_valptridx_check_success_condition, dxx_trap_##ERROR, FAILURE_STRING); \ static_cast( \ dxx_valptridx_check_success_condition || (ERROR::report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VA(__VA_ARGS__)), 0) \ ); \ } DXX_END_COMPOUND_STATEMENT ) #ifndef DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT #define DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT #endif template class valptridx::array_base_count_type { protected: union { unsigned count; /* * Use DXX_VALPTRIDX_FOR_EACH_PPI_TYPE to generate empty union * members based on basic_{i,v}val_member_factory * specializations. */ #define DXX_VALPTRIDX_DEFINE_MEMBER_FACTORIES(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX) \ valptridx::f ## IVPREFIX ## MCPREFIX ## PISUFFIX \ IVPREFIX ## MCPREFIX ## PISUFFIX DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(DXX_VALPTRIDX_DEFINE_MEMBER_FACTORIES, managed_type,,); #undef DXX_VALPTRIDX_DEFINE_MEMBER_FACTORIES }; constexpr array_base_count_type() : count(0) { } public: unsigned get_count() const { return count; } void set_count(const unsigned c) { count = c; } }; template < typename INTEGRAL_TYPE, std::size_t array_size_value, valptridx_untyped_utilities::report_error_style report_const_error_value, valptridx_untyped_utilities::report_error_style report_mutable_error_value > constexpr std::integral_constant valptridx_specialized_type_parameters::array_size; class valptridx_untyped_utilities::report_error_undefined { public: __attribute_cold DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(...) { } }; class valptridx_untyped_utilities::report_error_trap_terse { public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(...) { __builtin_trap(); } }; class valptridx_untyped_utilities::index_mismatch_trap_verbose { public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array, const unsigned long supplied_index, const void *const expected_pointer, const void *const actual_pointer) { __asm__ __volatile__("" :: DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS "rm" (array), "rm" (supplied_index), "rm" (expected_pointer), "rm" (actual_pointer)); __builtin_trap(); } }; class valptridx_untyped_utilities::index_range_trap_verbose { public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array, const unsigned long supplied_index) { __asm__ __volatile__("" :: DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS "rm" (array), "rm" (supplied_index)); __builtin_trap(); } }; class valptridx_untyped_utilities::null_pointer_trap_verbose { public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS) { __asm__ __volatile__("" :: DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS); __builtin_trap(); } __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array) { __asm__ __volatile__("" :: DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS "rm" (array)); __builtin_trap(); } }; template class valptridx

::index_mismatch_exception : public std::logic_error { DXX_INHERIT_CONSTRUCTORS(index_mismatch_exception, logic_error); public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type *, index_type, const_pointer_type, const_pointer_type); }; template class valptridx

::index_range_exception : public std::out_of_range { DXX_INHERIT_CONSTRUCTORS(index_range_exception, out_of_range); public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type *, long); }; template class valptridx

::null_pointer_exception : public std::logic_error { DXX_INHERIT_CONSTRUCTORS(null_pointer_exception, logic_error); public: __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS); __attribute_cold __attribute_noreturn DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type *); }; template template void valptridx::check_index_match(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type r, index_type i, const array_managed_type &a __attribute_unused) { const auto pi = &a[i]; DXX_VALPTRIDX_CHECK(pi == &r, handle_index_mismatch, "pointer/index mismatch", &a, i, pi, &r); } template template class Compare> typename valptridx::index_type valptridx::check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const index_type i, const array_managed_type *const a) { const std::size_t ss = i; DXX_VALPTRIDX_CHECK(Compare()(ss, array_size), handle_index_range_error, "invalid index used in array subscript", a, ss); return i; } template template void valptridx::check_null_pointer_conversion(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type p) { DXX_VALPTRIDX_CHECK(p, handle_null_pointer, "NULL pointer converted"); } template template void valptridx::check_null_pointer(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type p, const array_managed_type &a __attribute_unused) { DXX_VALPTRIDX_CHECK(p, handle_null_pointer, "NULL pointer used", &a); } template template void valptridx::check_implicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const managed_type &r, const array_managed_type &a) { check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS r, static_cast(&r) - static_cast(&a.front()), a); } template template void valptridx::check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type &r, std::size_t i, const array_managed_type &a) { check_index_match(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS r, i, a); check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS i, &a); } template class valptridx::partial_policy::require_valid { public: static constexpr std::false_type allow_nullptr{}; static constexpr std::false_type check_allowed_invalid_index(index_type) { return {}; } static constexpr bool check_nothrow_index(index_type i) { return std::less()(i, array_size); } }; template class valptridx::partial_policy::allow_invalid { public: static constexpr std::true_type allow_nullptr{}; static constexpr bool check_allowed_invalid_index(index_type i) { return i == static_cast(~0); } static constexpr bool check_nothrow_index(index_type i) { return check_allowed_invalid_index(i) || require_valid::check_nothrow_index(i); } }; template constexpr std::false_type valptridx::partial_policy::require_valid::allow_nullptr; template constexpr std::true_type valptridx::partial_policy::allow_invalid::allow_nullptr; template template