src: more cleanups; NFCI

This commit is contained in:
Markus F.X.J. Oberhumer 2022-09-15 01:14:38 +02:00
parent 81176716d5
commit b8b94ee89e
17 changed files with 226 additions and 150 deletions

View File

@ -63,7 +63,7 @@
#include "miniacc.h"
#if !(ACC_CC_CLANG || ACC_CC_GNUC || ACC_CC_MSC)
// other compilers may work, but we're NOT interested into supporting them
# error "only clang and gcc are officially supported"
# error "only clang, gcc and msvc are officially supported"
#endif
// UPX sanity checks for a sane compiler
#if !defined(UINT_MAX) || (UINT_MAX != 0xffffffffL)
@ -317,28 +317,24 @@ inline void NO_fprintf(FILE *, const char *, ...) {}
# define upx_memcpy_inline memcpy
#endif
#define __packed_struct(s) struct alignas(1) s {
#define __packed_struct_end() };
#define UNUSED(var) ACC_UNUSED(var)
#define COMPILE_TIME_ASSERT(e) ACC_COMPILE_TIME_ASSERT(e)
#define __COMPILE_TIME_ASSERT_ALIGNOF_SIZEOF(a,b) { \
// TODO cleanup: we now require C++14, so remove all __packed_struct usage
#define __packed_struct(s) struct alignas(1) s {
#define __packed_struct_end() };
#define COMPILE_TIME_ASSERT_ALIGNOF_USING_SIZEOF__(a,b) { \
typedef a acc_tmp_a_t; typedef b acc_tmp_b_t; \
__packed_struct(acc_tmp_t) acc_tmp_b_t x; acc_tmp_a_t y; acc_tmp_b_t z; __packed_struct_end() \
struct alignas(1) acc_tmp_t { acc_tmp_b_t x; acc_tmp_a_t y; acc_tmp_b_t z; }; \
COMPILE_TIME_ASSERT(sizeof(struct acc_tmp_t) == 2*sizeof(b)+sizeof(a)) \
COMPILE_TIME_ASSERT(sizeof(((acc_tmp_t*)nullptr)->x)+sizeof(((acc_tmp_t*)nullptr)->y)+sizeof(((acc_tmp_t*)nullptr)->z) == 2*sizeof(b)+sizeof(a)) \
}
#if defined(__acc_alignof)
# define __COMPILE_TIME_ASSERT_ALIGNOF(a,b) \
__COMPILE_TIME_ASSERT_ALIGNOF_SIZEOF(a,b) \
COMPILE_TIME_ASSERT(__acc_alignof(a) == sizeof(b))
#else
# define __COMPILE_TIME_ASSERT_ALIGNOF(a,b) \
__COMPILE_TIME_ASSERT_ALIGNOF_SIZEOF(a,b)
#endif
#define COMPILE_TIME_ASSERT_ALIGNED1(a) __COMPILE_TIME_ASSERT_ALIGNOF(a,char)
#define COMPILE_TIME_ASSERT_ALIGNOF__(a,b) \
COMPILE_TIME_ASSERT_ALIGNOF_USING_SIZEOF__(a,b) \
COMPILE_TIME_ASSERT(__acc_alignof(a) == sizeof(b)) \
COMPILE_TIME_ASSERT(alignof(a) == sizeof(b))
#define COMPILE_TIME_ASSERT_ALIGNED1(a) COMPILE_TIME_ASSERT_ALIGNOF__(a,char)
#define TABLESIZE(table) ((sizeof(table)/sizeof((table)[0])))
@ -397,23 +393,6 @@ constexpr bool string_ge(const char *a, const char *b) {
}
}
/*************************************************************************
// raw_bytes() - get underlying memory from checked buffers/pointers.
// This is overloaded by various utility classes like BoundedPtr,
// MemBuffer and Span.
//
// Note that the pointer type is retained, the "_bytes" hints size_in_bytes
**************************************************************************/
// default: for any regular pointer, raw_bytes() is just the pointer itself
template <class T>
inline T *raw_bytes(T *ptr, size_t size_in_bytes) {
if (size_in_bytes > 0) {
assert(ptr != nullptr);
}
return ptr;
}
/*************************************************************************
// constants
**************************************************************************/
@ -815,6 +794,24 @@ int upx_test_overlap ( const upx_bytep buf,
int method,
const upx_compress_result_t *cresult );
/*************************************************************************
// raw_bytes() - get underlying memory from checked buffers/pointers.
// This is overloaded by various utility classes like BoundedPtr,
// MemBuffer and Span.
//
// Note that the pointer type is retained, the "_bytes" hints size_in_bytes
**************************************************************************/
// default: for any regular pointer, raw_bytes() is just the pointer itself
template <class T>
inline T *raw_bytes(T *ptr, size_t size_in_bytes) {
if (size_in_bytes > 0) {
if __acc_very_unlikely (ptr == nullptr)
throwInternalError("raw_bytes unexpected NULL ptr");
}
return ptr;
}
#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
# if defined(INVALID_HANDLE_VALUE) || defined(MAKEWORD) || defined(RT_CURSOR)
@ -822,7 +819,6 @@ int upx_test_overlap ( const upx_bytep buf,
# endif
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

View File

@ -193,7 +193,7 @@ public:
#undef NORET
#if 1 && defined(__GNUC__)
#define NORET __attribute__((__noreturn__)) __acc_noinline
#define NORET __acc_noinline __attribute__((__noreturn__))
#else
#define NORET __acc_noinline
#endif

View File

@ -75,7 +75,7 @@ options_t *opt = &global_options;
**************************************************************************/
template <size_t N>
static void test_options(const char *(&a)[N]) {
static inline void test_options(const char *(&a)[N]) {
(void) main_get_options((int) (N - 1), ACC_UNCONST_CAST(char **, a));
}
@ -85,42 +85,59 @@ TEST_CASE("getopt") {
opt = &local_options;
opt->reset();
opt->debug.getopt_throw_instead_of_exit = true;
const char a0[] = "<argv0>";
static const char a0[] = "<argv0>";
SUBCASE("issue 587a") {
SUBCASE("issue 587") {
const char *a[] = {a0, "--brute", "--lzma", nullptr};
CHECK(!opt->all_methods);
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == 1);
}
SUBCASE("issue 587b") {
SUBCASE("issue 587") {
const char *a[] = {a0, "--lzma", "--brute", nullptr};
CHECK(!opt->all_methods);
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == 1);
}
SUBCASE("issue 587c") {
SUBCASE("issue 587") {
const char *a[] = {a0, "--brute", "--no-lzma", nullptr};
CHECK(!opt->all_methods);
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == -1);
}
SUBCASE("issue 587d") {
SUBCASE("issue 587") {
const char *a[] = {a0, "--no-lzma", "--brute", nullptr};
CHECK(!opt->all_methods);
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == -1);
}
SUBCASE("issue 587e") {
const char *a[] = {a0, "--no-lzma", "--all-methods", nullptr};
SUBCASE("issue 587") {
const char *a[] = {a0, "--no-lzma", "--lzma", nullptr};
test_options(a);
CHECK(!opt->all_methods);
CHECK(opt->all_methods_use_lzma == 1);
CHECK(opt->method == M_LZMA);
}
SUBCASE("issue 587") {
const char *a[] = {a0, "--no-lzma", "--lzma", "--brute", nullptr};
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == 1);
CHECK(opt->method == -1);
}
SUBCASE("issue 587") {
const char *a[] = {a0, "--lzma", "--no-lzma", nullptr};
test_options(a);
CHECK(!opt->all_methods);
CHECK(opt->all_methods_use_lzma == -1);
CHECK(opt->method == -1);
}
SUBCASE("issue 587") {
const char *a[] = {a0, "--lzma", "--no-lzma", "--brute", nullptr};
test_options(a);
CHECK(opt->all_methods);
CHECK(opt->all_methods_use_lzma == -1);
CHECK(opt->method == -1);
}
opt = saved_opt;

View File

@ -94,7 +94,7 @@ unsigned UiPacker::update_fu_len = 0;
static const char header_line1[] = " File size Ratio Format Name\n";
static char header_line2[] = " -------------------- ------ ----------- -----------\n";
static char progress_filler[] = ".*[]";
static char progress_filler[4 + 1] = ".*[]";
static void init_global_constants(void) {
#if 0 && (ACC_OS_DOS16 || ACC_OS_DOS32)
@ -399,7 +399,7 @@ void UiPacker::doCallback(unsigned isize, unsigned osize) {
char *m = &s->msg_buf[s->bar_pos];
*m++ = progress_filler[2];
for (i = 0; i < s->bar_len; i++)
*m++ = progress_filler[i <= pos];
*m++ = progress_filler[i <= pos ? 1 : 0];
*m++ = progress_filler[3];
// compute current compression ratio

View File

@ -141,10 +141,6 @@ struct TestBELE {
COMPILE_TIME_ASSERT(sizeof(test2_t) == 1 + 3 * sizeof(T))
COMPILE_TIME_ASSERT_ALIGNED1(test2_t)
COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T))
#if defined(__acc_alignof)
COMPILE_TIME_ASSERT(__acc_alignof(t1) == 1)
COMPILE_TIME_ASSERT(__acc_alignof(t2) == 1)
#endif
#if 1
T allbits;
allbits = 0;

View File

@ -107,9 +107,9 @@ static unsigned width(unsigned x) {
static inline unsigned umax(unsigned a, unsigned b) { return (a >= b) ? a : b; }
unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra) {
size_t const z = uncompressed_size; // fewer keystrokes and display columns
size_t const w = umax(8, width(z - 1)); // ignore tiny offsets
size_t bytes = mem_size(1, z);
unsigned const z = uncompressed_size; // fewer keystrokes and display columns
unsigned const w = umax(8, width(z - 1)); // ignore tiny offsets
unsigned bytes = ACC_ICONV(unsigned, mem_size(1, z)); // check
// Worst matching: All match at max_offset, which implies 3==min_match
// All literal: 1 bit overhead per literal byte
bytes = umax(bytes, bytes + z / 8);
@ -119,11 +119,11 @@ unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned e
bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8);
// extra + 256 safety for rounding
bytes = mem_size(1, bytes, extra, 256);
return ACC_ICONV(unsigned, bytes);
return bytes;
}
unsigned MemBuffer::getSizeForUncompression(unsigned uncompressed_size, unsigned extra) {
size_t bytes = mem_size(1, uncompressed_size, extra);
size_t bytes = mem_size(1, uncompressed_size, extra); // check
return ACC_ICONV(unsigned, bytes);
}
@ -152,9 +152,9 @@ void MemBuffer::fill(unsigned off, unsigned len, int value) {
//
**************************************************************************/
#define PTR(p) ((unsigned) ((upx_uintptr_t)(p) &0xffffffff))
#define MAGIC1(p) (PTR(p) ^ 0xfefdbeeb)
#define MAGIC2(p) (PTR(p) ^ 0xfefdbeeb ^ 0x80024001)
#define PTR_BITS(p) ((unsigned) ((upx_uintptr_t)(p) &0xffffffff))
#define MAGIC1(p) ((PTR_BITS(p) ^ 0xfefdbeeb) | 1)
#define MAGIC2(p) ((PTR_BITS(p) ^ 0xfefdbeeb ^ 0x80024011) | 1)
unsigned MemBuffer::global_alloc_counter = 0;
@ -162,11 +162,11 @@ void MemBuffer::checkState() const {
if (!b)
throwInternalError("block not allocated");
if (use_simple_mcheck()) {
if (get_be32(b - 4) != MAGIC1(b))
if (get_ne32(b - 4) != MAGIC1(b))
throwInternalError("memory clobbered before allocated block 1");
if (get_be32(b - 8) != b_size_in_bytes)
if (get_ne32(b - 8) != b_size_in_bytes)
throwInternalError("memory clobbered before allocated block 2");
if (get_be32(b + b_size_in_bytes) != MAGIC2(b))
if (get_ne32(b + b_size_in_bytes) != MAGIC2(b))
throwInternalError("memory clobbered past end of allocated block");
}
}
@ -181,18 +181,17 @@ void MemBuffer::alloc(upx_uint64_t size) {
unsigned char *p = (unsigned char *) malloc(bytes);
if (!p)
throwOutOfMemoryException();
b = p;
b_size_in_bytes = ACC_ICONV(unsigned, size);
if (use_simple_mcheck()) {
b = p + 16;
// store magic constants to detect buffer overruns
set_be32(b - 8, b_size_in_bytes);
set_be32(b - 4, MAGIC1(b));
set_be32(b + b_size_in_bytes, MAGIC2(b));
set_be32(b + b_size_in_bytes + 4, global_alloc_counter++);
} else
b = p;
#if defined(__SANITIZE_ADDRESS__) || DEBUG
set_ne32(b - 8, b_size_in_bytes);
set_ne32(b - 4, MAGIC1(b));
set_ne32(b + b_size_in_bytes, MAGIC2(b));
set_ne32(b + b_size_in_bytes + 4, global_alloc_counter++);
}
#if !defined(__SANITIZE_ADDRESS__) && 0
fill(0, b_size_in_bytes, (rand() & 0xff) | 1); // debug
(void) VALGRIND_MAKE_MEM_UNDEFINED(b, b_size_in_bytes);
#endif
@ -203,10 +202,10 @@ void MemBuffer::dealloc() {
checkState();
if (use_simple_mcheck()) {
// clear magic constants
set_be32(b - 8, 0);
set_be32(b - 4, 0);
set_be32(b + b_size_in_bytes, 0);
set_be32(b + b_size_in_bytes + 4, 0);
set_ne32(b - 8, 0);
set_ne32(b - 4, 0);
set_ne32(b + b_size_in_bytes, 0);
set_ne32(b + b_size_in_bytes + 4, 0);
//
::free(b - 16);
} else
@ -218,4 +217,29 @@ void MemBuffer::dealloc() {
}
}
/*************************************************************************
//
**************************************************************************/
TEST_CASE("MemBuffer") {
MemBuffer mb;
CHECK_THROWS(mb.checkState());
CHECK_THROWS(mb.alloc(0x30000000 + 1));
CHECK(raw_bytes(mb, 0) == nullptr);
CHECK_THROWS(raw_bytes(mb, 1));
mb.alloc(64);
mb.checkState();
CHECK(raw_bytes(mb, 64) != nullptr);
CHECK(raw_bytes(mb, 64) == mb.getVoidPtr());
CHECK_THROWS(raw_bytes(mb, 65));
if (use_simple_mcheck()) {
upx_byte *b = raw_bytes(mb, 0);
unsigned magic1 = get_ne32(b - 4);
set_ne32(b - 4, magic1 ^ 1);
CHECK_THROWS(mb.checkState());
set_ne32(b - 4, magic1);
mb.checkState();
}
}
/* vim:set ts=4 sw=4 et: */

View File

@ -48,20 +48,24 @@ public:
// NOTE: for fully bound-checked pointer use SPAN_S from xspan.h
operator pointer() const { return b; }
template <class U, class V = typename std::enable_if<std::is_integral<U>::value, U>::type>
pointer operator+(V n) const {
size_t bytes = mem_size(sizeof(T), n); // check
return raw_bytes(bytes) + n;
template <class U,
class /*Dummy*/ = typename std::enable_if<std::is_integral<U>::value, U>::type>
pointer operator+(U n) const {
size_t bytes = mem_size(sizeof(T), n); // check mem_size
return raw_bytes(bytes) + n; // and check bytes
}
// NOT allowed; use raw_bytes() instead
template <class U, class V = typename std::enable_if<std::is_integral<U>::value, U>::type>
pointer operator-(V n) const = delete;
template <class U,
class /*Dummy*/ = typename std::enable_if<std::is_integral<U>::value, U>::type>
pointer operator-(U n) const = delete;
pointer raw_bytes(size_t bytes) const {
if (bytes > 0) {
assert(b != nullptr);
assert(bytes <= b_size_in_bytes);
if __acc_very_unlikely (b == nullptr)
throwInternalError("MemBuffer raw_bytes unexpected NULL ptr");
if __acc_very_unlikely (bytes > b_size_in_bytes)
throwInternalError("MemBuffer raw_bytes invalid size");
}
return b;
}

View File

@ -31,8 +31,8 @@
// UPX version of string functions, with assertions and sane limits
**************************************************************************/
#undef vsnprintf
int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) {
#undef vsnprintf
size_t size;
// preconditions
@ -56,6 +56,7 @@ int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_l
}
return ACC_ICONV(int, size - 1); // snprintf() returns length, not size
#define vsnprintf upx_safe_vsnprintf
}
int upx_safe_snprintf(char *str, upx_rsize_t max_size, const char *format, ...) {
@ -113,12 +114,13 @@ char *upx_safe_xprintf(const char *format, ...) {
return ptr;
}
#undef strlen
upx_rsize_t upx_safe_strlen(const char *s) {
#undef strlen
assert(s != nullptr);
size_t len = strlen(s);
assert(len < UPX_RSIZE_MAX_STR);
return len;
#define strlen upx_safe_strlen
}
/* vim:set ts=4 sw=4 et: */

View File

@ -249,20 +249,20 @@ int __acc_cdecl_qsort le64_compare_signed(const void *e1, const void *e2) {
}
/*************************************************************************
// find util
// find and mem_replace util
**************************************************************************/
int find(const void *b, int blen, const void *what, int wlen) {
if (b == nullptr || blen <= 0 || what == nullptr || wlen <= 0)
int find(const void *buf, int blen, const void *what, int wlen) {
// nullptr is explicitly allowed here
if (buf == nullptr || blen <= 0 || what == nullptr || wlen <= 0)
return -1;
int i;
const unsigned char *base = (const unsigned char *) b;
unsigned char firstc = *(const unsigned char *) what;
const unsigned char *b = (const unsigned char *) buf;
unsigned char first_byte = *(const unsigned char *) what;
blen -= wlen;
for (i = 0; i <= blen; i++, base++)
if (*base == firstc && memcmp(base, what, wlen) == 0)
for (int i = 0; i <= blen; i++, b++)
if (*b == first_byte && memcmp(b, what, wlen) == 0)
return i;
return -1;
@ -305,6 +305,7 @@ int find_le64(const void *b, int blen, upx_uint64_t what) {
}
TEST_CASE("find") {
CHECK(find(nullptr, -1, nullptr, -1) == -1);
static const unsigned char b[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
CHECK(find(b, 16, b, 0) == -1);
for (int i = 0; i < 16; i++) {
@ -320,10 +321,12 @@ TEST_CASE("find") {
CHECK(find_le32(b, 16, 0x07060504) == 4);
CHECK(find_be64(b, 16, 0x08090a0b0c0d0e0fULL) == 8);
CHECK(find_le64(b, 16, 0x0f0e0d0c0b0a0908ULL) == 8);
CHECK(find_be64(b, 15, 0x08090a0b0c0d0e0fULL) == -1);
CHECK(find_le64(b, 15, 0x0f0e0d0c0b0a0908ULL) == -1);
}
int mem_replace(void *bb, int blen, const void *what, int wlen, const void *r) {
unsigned char *b = (unsigned char *) bb;
int mem_replace(void *buf, int blen, const void *what, int wlen, const void *replacement) {
unsigned char *b = (unsigned char *) buf;
int boff = 0;
int n = 0;
@ -332,7 +335,7 @@ int mem_replace(void *bb, int blen, const void *what, int wlen, const void *r) {
if (off < 0)
break;
boff += off;
memcpy(b + boff, r, wlen);
memcpy(b + boff, replacement, wlen);
boff += wlen;
n++;
}

View File

@ -40,7 +40,7 @@ inline bool mem_size_valid_bytes(upx_uint64_t bytes) noexcept { return bytes <=
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
upx_uint64_t extra2 = 0) noexcept;
// new with asserted size; will throw on failure
// "new" with asserted size; will throw on failure
#define New(type, n) new type[mem_size_get_n(sizeof(type), n)]
// will throw on invalid size
@ -75,8 +75,8 @@ inline void mem_clear(void *p, size_t n) {
memset(p, 0, n);
}
// ptrdiff_t with nullptr check and asserted size; will throw on failure
// WARNING: returns size_in_bytes, not number of elements!
// ptrdiff_t with nullptr checks and asserted size; will throw on failure
// NOTE: returns size_in_bytes, not number of elements!
int ptr_diff_bytes(const void *a, const void *b);
unsigned ptr_udiff_bytes(const void *a, const void *b); // asserts a >= b
@ -96,6 +96,16 @@ ptr_udiff(const T *a, const U *b) {
// misc. support functions
**************************************************************************/
int find(const void *b, int blen, const void *what, int wlen);
int find_be16(const void *b, int blen, unsigned what);
int find_be32(const void *b, int blen, unsigned what);
int find_be64(const void *b, int blen, upx_uint64_t what);
int find_le16(const void *b, int blen, unsigned what);
int find_le32(const void *b, int blen, unsigned what);
int find_le64(const void *b, int blen, upx_uint64_t what);
int mem_replace(void *b, int blen, const void *what, int wlen, const void *r);
char *fn_basename(const char *name);
int fn_strcmp(const char *n1, const char *n2);
char *fn_strlwr(char *n);
@ -110,16 +120,6 @@ unsigned get_ratio(upx_uint64_t u_len, upx_uint64_t c_len);
bool set_method_name(char *buf, size_t size, int method, int level);
void center_string(char *buf, size_t size, const char *s);
int find(const void *b, int blen, const void *what, int wlen);
int find_be16(const void *b, int blen, unsigned what);
int find_be32(const void *b, int blen, unsigned what);
int find_be64(const void *b, int blen, upx_uint64_t what);
int find_le16(const void *b, int blen, unsigned what);
int find_le32(const void *b, int blen, unsigned what);
int find_le64(const void *b, int blen, upx_uint64_t what);
int mem_replace(void *b, int blen, const void *what, int wlen, const void *r);
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

View File

@ -30,7 +30,7 @@
SPAN_NAMESPACE_BEGIN
unsigned long long span_check_stats_check_range;
unsigned long long span_check_stats_check_range = 0;
__acc_noinline void span_fail_nullptr() {
throwCantUnpack("span unexpected NULL pointer; take care!");

View File

@ -52,12 +52,20 @@ pointer ptr; // current view into (base, base+size_in_bytes) iff base != nullptr
pointer base;
size_type size_in_bytes;
private:
// disable taking the address => force passing by reference
// [I'm not too sure about this design decision, but we can always allow it if needed]
Self *operator&() const SPAN_DELETED_FUNCTION;
// debug - internal sanity check; also serves as pseudo-documentation
#if DEBUG || 1
__acc_noinline void assertInvariants() const {
if __acc_cte (configRequirePtr)
assert(ptr != nullptr);
if __acc_cte (configRequireBase)
assert(base != nullptr);
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
span_check_range(ptr, base, size_in_bytes);
}
#else
__acc_forceinline void assertInvariants() const {}
#endif
private:
static __acc_forceinline pointer makeNotNull(pointer p) {
if __acc_very_unlikely (p == nullptr)
span_fail_nullptr();
@ -85,19 +93,6 @@ __acc_forceinline pointer ensureBase() const {
span_fail_nullptr();
return ptr;
}
// debug - extra internal sanity checks
#if DEBUG || 1
__acc_noinline void assertInvariants() const {
if __acc_cte (configRequirePtr)
assert(ptr != nullptr);
if __acc_cte (configRequireBase)
assert(base != nullptr);
if __acc_cte ((configRequirePtr || ptr != nullptr) && (configRequireBase || base != nullptr))
span_check_range(ptr, base, size_in_bytes);
}
#else
__acc_forceinline void assertInvariants() const {}
#endif
public:
inline ~CSelf() {}
@ -397,6 +392,10 @@ pointer check_add(pointer p, ptrdiff_t n) const {
return p;
}
// disable taking the address => force passing by reference
// [I'm not too sure about this design decision, but we can always allow it if needed]
Self *operator&() const SPAN_DELETED_FUNCTION;
public: // raw access
pointer raw_ptr() const { return ptr; }
pointer raw_base() const { return base; }

View File

@ -64,17 +64,21 @@ public:
#endif
inline ~CSelf() {}
inline CSelf() {}
inline CSelf() { assertInvariants(); }
// constructors from pointers
CSelf(pointer p) : ptr(makePtr(p)) {}
CSelf(pointer p) : ptr(makePtr(p)) { assertInvariants(); }
template <class U>
CSelf(U *p, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(makePtr(p)) {}
CSelf(U *p, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(makePtr(p)) {
assertInvariants();
}
// constructors
CSelf(const Self &other) : ptr(other.ptr) {}
CSelf(const Self &other) : ptr(other.ptr) { assertInvariants(); }
template <class U>
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(other.ptr) {}
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A) : ptr(other.ptr) {
assertInvariants();
}
Self &assign(const Self &other) {
assertInvariants();
@ -87,10 +91,11 @@ public:
// assignment
Self &operator=(const Self &other) { return assign(other); }
// FIXME: this is not called !!
template <class U>
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
operator=(U *other) {
assert(0);
// assert(0);
return assign(Self(other));
}
@ -98,7 +103,7 @@ public:
template <class U>
SPAN_REQUIRES_CONVERTIBLE_R(Self &)
operator=(const CSelf<U> &other) {
assert(0);
// assert(0);
return assign(Self(other));
}
@ -187,6 +192,7 @@ public: // raw access
#undef CSelf
};
// raw_bytes overload
template <class T>
inline T *raw_bytes(const Ptr<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);

View File

@ -48,22 +48,30 @@ private:
#include "xspan_impl_common.h"
public:
// constructors from pointers
CSelf(pointer first) : ptr(first), base(nullptr), size_in_bytes(0) {}
CSelf(pointer first) : ptr(first), base(nullptr), size_in_bytes(0) { assertInvariants(); }
// constructors
CSelf(const Self &other)
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
// constructors from Span friends
template <class U>
CSelf(const PtrOrSpan<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const Span<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ptr), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
// assignment from Span friends
template <class U>
@ -82,6 +90,7 @@ public:
#undef CSelf
};
// raw_bytes overload
template <class T>
inline T *raw_bytes(const PtrOrSpanOrNull<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);

View File

@ -48,23 +48,33 @@ private:
#include "xspan_impl_common.h"
public:
// constructors from pointers
CSelf(pointer first) : ptr(makePtr(first)), base(nullptr), size_in_bytes(0) {}
CSelf(pointer first) : ptr(makePtr(first)), base(nullptr), size_in_bytes(0) {
assertInvariants();
}
// constructors
CSelf(const Self &other)
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
// constructors from Span friends
template <class U>
CSelf(const Span<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
template <class U>
CSelf(const PtrOrSpanOrNull<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.base), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
#endif
// assignment from Span friends
@ -107,6 +117,7 @@ public:
#undef CSelf
};
// raw_bytes overload
template <class T>
inline T *raw_bytes(const PtrOrSpan<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);

View File

@ -52,19 +52,27 @@ public:
// constructors
CSelf(const Self &other)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const CSelf<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
// constructors from Span friends
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
template <class U>
CSelf(const PtrOrSpanOrNull<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
template <class U>
CSelf(const PtrOrSpan<U> &other, SPAN_REQUIRES_CONVERTIBLE_A)
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {}
: ptr(other.ensurePtr()), base(other.ensureBase()), size_in_bytes(other.size_in_bytes) {
assertInvariants();
}
#endif
// assignment from Span friends
@ -109,6 +117,7 @@ public:
#undef CSelf
};
// raw_bytes overload
template <class T>
inline T *raw_bytes(const Span<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);