dxx-rebirth/common/main/valptridx.tcc

117 lines
5.4 KiB
Plaintext
Raw Normal View History

/*
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
* 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.
*/
2016-01-26 03:45:08 +00:00
#pragma once
#include <cstdio>
#include <inttypes.h>
#include "valptridx.h"
#include "compiler-addressof.h"
#if DXX_VALPTRIDX_REPORT_ERROR_STYLE == DXX_VALPTRIDX_ERROR_STYLE_TREAT_AS_EXCEPTION
namespace untyped_index_mismatch_exception
{
#ifdef DXX_VALPTRIDX_ENABLE_REPORT_FILENAME
#define REPORT_STANDARD_LEADER_TEXT "%s:%u: "
#else
#define REPORT_STANDARD_LEADER_TEXT
#endif
Switch valptridx array_size error reporting to %lu x86_64-w64-mingw32-g++ -Wformat handling misparses the std::size_t format string, causing a spurious error. common/main/valptridx.tcc: In function 'void untyped_index_mismatch_exception::prepare_report(const char*, unsigned int, const void*, long int, const void*, const void*, char (&)[229], std::size_t)': common/main/valptridx.tcc:36:182: error: format '%u' expects argument of type 'unsigned int', but argument 7 has type 'std::size_t {aka long long unsigned int}' [-Werror=format=] This occurs even though the processed text uses %I64u (which is correct for a `long long unsigned int`), not %u as shown in the error message. static void prepare_report(const char *const filename, const unsigned lineno, const void *const array_base, const long supplied_index, const void *const expected_pointer, const void *const actual_pointer, char (&buf)[report_buffer_size], const std::size_t array_size) { snprintf(buf, sizeof(buf), "%s:%u: " "pointer/index mismatch:" " base=%p size=%" "I64u" " index=%li expected=%p actual=%p", filename, lineno, array_base, array_size, supplied_index, expected_pointer, actual_pointer); } In practice, all such sizes will fit in `unsigned int` because they are the dimension of an array of large structures. Switch all platforms to use `unsigned long`, which works everywhere and is at least as big as `unsigned int`. Using `unsigned long` produces the same size as `std::size_t` on all platforms other than Win64, where `unsigned long` is only 32 bits due to the strange LLP64 model Microsoft picked.
2017-04-22 21:23:55 +00:00
#define REPORT_STANDARD_FORMAT " base=%p size=%lu"
#define REPORT_STANDARD_ARGUMENTS array_base, array_size
#define REPORT_STANDARD_SIZE ( \
sizeof(REPORT_FORMAT_STRING) + \
42 /* length of longest filename in `git ls-files` */ + \
sizeof("65535") + /* USHORT_MAX for lineno */ \
sizeof("0x0000000000000000") + /* for pointer from base=%p */ \
sizeof("18446744073709551615") /* for size from size=%lu */ \
)
#define REPORT_FORMAT_STRING REPORT_STANDARD_LEADER_TEXT "pointer/index mismatch:" REPORT_STANDARD_FORMAT " index=%li expected=%p actual=%p"
static constexpr std::size_t report_buffer_size = REPORT_STANDARD_SIZE + (sizeof("0x0000000000000000") * 2) + sizeof("18446744073709551615");
__attribute_cold
Switch valptridx array_size error reporting to %lu x86_64-w64-mingw32-g++ -Wformat handling misparses the std::size_t format string, causing a spurious error. common/main/valptridx.tcc: In function 'void untyped_index_mismatch_exception::prepare_report(const char*, unsigned int, const void*, long int, const void*, const void*, char (&)[229], std::size_t)': common/main/valptridx.tcc:36:182: error: format '%u' expects argument of type 'unsigned int', but argument 7 has type 'std::size_t {aka long long unsigned int}' [-Werror=format=] This occurs even though the processed text uses %I64u (which is correct for a `long long unsigned int`), not %u as shown in the error message. static void prepare_report(const char *const filename, const unsigned lineno, const void *const array_base, const long supplied_index, const void *const expected_pointer, const void *const actual_pointer, char (&buf)[report_buffer_size], const std::size_t array_size) { snprintf(buf, sizeof(buf), "%s:%u: " "pointer/index mismatch:" " base=%p size=%" "I64u" " index=%li expected=%p actual=%p", filename, lineno, array_base, array_size, supplied_index, expected_pointer, actual_pointer); } In practice, all such sizes will fit in `unsigned int` because they are the dimension of an array of large structures. Switch all platforms to use `unsigned long`, which works everywhere and is at least as big as `unsigned int`. Using `unsigned long` produces the same size as `std::size_t` on all platforms other than Win64, where `unsigned long` is only 32 bits due to the strange LLP64 model Microsoft picked.
2017-04-22 21:23:55 +00:00
static void prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array_base, const long supplied_index, const void *const expected_pointer, const void *const actual_pointer, char (&buf)[report_buffer_size], const unsigned long array_size)
{
snprintf(buf, sizeof(buf), REPORT_FORMAT_STRING, DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS REPORT_STANDARD_ARGUMENTS, supplied_index, expected_pointer, actual_pointer);
}
#undef REPORT_FORMAT_STRING
};
namespace untyped_index_range_exception
{
#define REPORT_FORMAT_STRING REPORT_STANDARD_LEADER_TEXT "invalid index used in array subscript:" REPORT_STANDARD_FORMAT " index=%li"
static constexpr std::size_t report_buffer_size = REPORT_STANDARD_SIZE + sizeof("18446744073709551615");
__attribute_cold
Switch valptridx array_size error reporting to %lu x86_64-w64-mingw32-g++ -Wformat handling misparses the std::size_t format string, causing a spurious error. common/main/valptridx.tcc: In function 'void untyped_index_mismatch_exception::prepare_report(const char*, unsigned int, const void*, long int, const void*, const void*, char (&)[229], std::size_t)': common/main/valptridx.tcc:36:182: error: format '%u' expects argument of type 'unsigned int', but argument 7 has type 'std::size_t {aka long long unsigned int}' [-Werror=format=] This occurs even though the processed text uses %I64u (which is correct for a `long long unsigned int`), not %u as shown in the error message. static void prepare_report(const char *const filename, const unsigned lineno, const void *const array_base, const long supplied_index, const void *const expected_pointer, const void *const actual_pointer, char (&buf)[report_buffer_size], const std::size_t array_size) { snprintf(buf, sizeof(buf), "%s:%u: " "pointer/index mismatch:" " base=%p size=%" "I64u" " index=%li expected=%p actual=%p", filename, lineno, array_base, array_size, supplied_index, expected_pointer, actual_pointer); } In practice, all such sizes will fit in `unsigned int` because they are the dimension of an array of large structures. Switch all platforms to use `unsigned long`, which works everywhere and is at least as big as `unsigned int`. Using `unsigned long` produces the same size as `std::size_t` on all platforms other than Win64, where `unsigned long` is only 32 bits due to the strange LLP64 model Microsoft picked.
2017-04-22 21:23:55 +00:00
static void prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array_base, const long supplied_index, char (&buf)[report_buffer_size], const unsigned long array_size)
{
snprintf(buf, sizeof(buf), REPORT_FORMAT_STRING, DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS REPORT_STANDARD_ARGUMENTS, supplied_index);
}
#undef REPORT_FORMAT_STRING
};
namespace untyped_null_pointer_conversion_exception
{
#define REPORT_FORMAT_STRING REPORT_STANDARD_LEADER_TEXT "NULL pointer converted"
static constexpr std::size_t report_buffer_size = REPORT_STANDARD_SIZE;
__attribute_cold
static void prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS char (&buf)[report_buffer_size])
{
snprintf(buf, sizeof(buf), REPORT_FORMAT_STRING DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_PASS_VARS);
}
#undef REPORT_FORMAT_STRING
}
namespace untyped_null_pointer_exception
{
#define REPORT_FORMAT_STRING REPORT_STANDARD_LEADER_TEXT "NULL pointer used:" REPORT_STANDARD_FORMAT
static constexpr std::size_t report_buffer_size = REPORT_STANDARD_SIZE;
__attribute_cold
Switch valptridx array_size error reporting to %lu x86_64-w64-mingw32-g++ -Wformat handling misparses the std::size_t format string, causing a spurious error. common/main/valptridx.tcc: In function 'void untyped_index_mismatch_exception::prepare_report(const char*, unsigned int, const void*, long int, const void*, const void*, char (&)[229], std::size_t)': common/main/valptridx.tcc:36:182: error: format '%u' expects argument of type 'unsigned int', but argument 7 has type 'std::size_t {aka long long unsigned int}' [-Werror=format=] This occurs even though the processed text uses %I64u (which is correct for a `long long unsigned int`), not %u as shown in the error message. static void prepare_report(const char *const filename, const unsigned lineno, const void *const array_base, const long supplied_index, const void *const expected_pointer, const void *const actual_pointer, char (&buf)[report_buffer_size], const std::size_t array_size) { snprintf(buf, sizeof(buf), "%s:%u: " "pointer/index mismatch:" " base=%p size=%" "I64u" " index=%li expected=%p actual=%p", filename, lineno, array_base, array_size, supplied_index, expected_pointer, actual_pointer); } In practice, all such sizes will fit in `unsigned int` because they are the dimension of an array of large structures. Switch all platforms to use `unsigned long`, which works everywhere and is at least as big as `unsigned int`. Using `unsigned long` produces the same size as `std::size_t` on all platforms other than Win64, where `unsigned long` is only 32 bits due to the strange LLP64 model Microsoft picked.
2017-04-22 21:23:55 +00:00
static void prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array_base, char (&buf)[report_buffer_size], const unsigned long array_size)
{
snprintf(buf, sizeof(buf), REPORT_FORMAT_STRING, DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS REPORT_STANDARD_ARGUMENTS);
}
#undef REPORT_FORMAT_STRING
#undef REPORT_STANDARD_LEADER_TEXT
#undef REPORT_STANDARD_SIZE
#undef REPORT_STANDARD_ARGUMENTS
#undef REPORT_STANDARD_FORMAT
};
template <typename managed_type>
void valptridx<managed_type>::index_mismatch_exception::report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type &array, const index_type supplied_index, const const_pointer_type expected_pointer, const const_pointer_type actual_pointer)
{
using namespace untyped_index_mismatch_exception;
char buf[report_buffer_size];
prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS addressof(array), supplied_index, expected_pointer, actual_pointer, buf, array.size());
throw index_mismatch_exception(buf);
}
template <typename managed_type>
void valptridx<managed_type>::index_range_exception::report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type *array, const long supplied_index)
{
using namespace untyped_index_range_exception;
char buf[report_buffer_size];
prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS array, supplied_index, buf, array_size);
throw index_range_exception(buf);
}
template <typename managed_type>
void valptridx<managed_type>::null_pointer_exception::report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS)
{
using namespace untyped_null_pointer_conversion_exception;
char buf[report_buffer_size];
prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS buf);
throw null_pointer_exception(buf);
}
template <typename managed_type>
void valptridx<managed_type>::null_pointer_exception::report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const array_managed_type &array)
{
using namespace untyped_null_pointer_exception;
char buf[report_buffer_size];
prepare_report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS addressof(array), buf, array.size());
throw null_pointer_exception(buf);
}
#endif