src: portability updates
This commit is contained in:
+1
-2
@@ -219,8 +219,7 @@ forceinline constexpr T max(const T &a, const T &b) noexcept {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool is_uminmax_type =
|
||||
is_same_any_v<T, upx_uint8_t, upx_uint16_t, upx_uint32_t, upx_uint64_t, unsigned long, size_t>;
|
||||
inline constexpr bool is_uminmax_type = std::is_integral_v<T> && std::is_unsigned_v<T>;
|
||||
|
||||
template <class T, class = std::enable_if_t<is_uminmax_type<T>, T> >
|
||||
forceinline constexpr T umin(const T &a, const T &b) noexcept {
|
||||
|
||||
@@ -49,6 +49,8 @@ unsigned membuffer_get_size(MemBuffer &mb) noexcept { return mb.getSize(); }
|
||||
|
||||
#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_MEMORY__)
|
||||
static forceinline constexpr bool use_simple_mcheck() noexcept { return false; }
|
||||
#elif defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
static forceinline constexpr bool use_simple_mcheck() noexcept { return false; }
|
||||
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
|
||||
static bool use_simple_mcheck_flag;
|
||||
static noinline void init_use_simple_mcheck() noexcept {
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/* system_check_predefs.h -- check pre-defined macros
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2024 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
// windows defines
|
||||
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN64__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
#error "unexpected _WIN64"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(__MINGW32__)
|
||||
#error "missing __MINGW32__"
|
||||
#endif
|
||||
#if defined(__MINGW32__) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(_WIN64)
|
||||
#error "missing _WIN64"
|
||||
#endif
|
||||
#if defined(_WIN64) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
|
||||
// available since gcc-4.3 (2008), clang-2.7 (2010) and msvc-20XX
|
||||
#if !defined(__COUNTER__)
|
||||
#error "missing __COUNTER__"
|
||||
#endif
|
||||
|
||||
// fundamental type sizes - these are pre-defined since gcc-4.3 (2008) and clang-2.8 (2010)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__SIZEOF_SHORT__)
|
||||
#error "missing __SIZEOF_SHORT__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_INT__)
|
||||
#error "missing __SIZEOF_INT__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_LONG__)
|
||||
#error "missing __SIZEOF_LONG__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_LONG_LONG__)
|
||||
#error "missing __SIZEOF_LONG_LONG__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_PTRDIFF_T__)
|
||||
#error "missing __SIZEOF_PTRDIFF_T__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_SIZE_T__)
|
||||
#error "missing __SIZEOF_SIZE_T__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_POINTER__)
|
||||
#error "missing __SIZEOF_POINTER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// fundamental types - these are pre-defined since gcc-4.5 (2010) and clang-3.5 (2014)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__PTRDIFF_TYPE__)
|
||||
#error "missing __PTRDIFF_TYPE__"
|
||||
#endif
|
||||
#if !defined(__SIZE_TYPE__)
|
||||
#error "missing __SIZE_TYPE__"
|
||||
#endif
|
||||
#if !defined(__INTPTR_TYPE__)
|
||||
#error "missing __INTPTR_TYPE__"
|
||||
#endif
|
||||
#if !defined(__UINTPTR_TYPE__)
|
||||
#error "missing __UINTPTR_TYPE__"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PTRADDR_TYPE__) && !defined(__PTRADDR_WIDTH__)
|
||||
#error "missing __PTRADDR_WIDTH__"
|
||||
#elif defined(__PTRADDR_WIDTH__) && !defined(__PTRADDR_TYPE__)
|
||||
#error "missing __PTRADDR_TYPE__"
|
||||
#endif
|
||||
|
||||
// byte order - these are pre-defined since gcc-4.6 (2011) and clang-3.2 (2012)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_LITTLE_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_LITTLE_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER__) || (__BYTE_ORDER__ + 0 == 0)
|
||||
#error "missing __BYTE_ORDER__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 != 4321)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 != 1234)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
|
||||
#error "unexpected __BYTE_ORDER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// pic and pie
|
||||
#if defined(__PIC__) && defined(__pic__)
|
||||
#if (__PIC__ + 0) != (__pic__ + 0)
|
||||
#error "unexpected __PIC__ vs __pic__ mismatch"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIC__)
|
||||
#if (__PIC__ != 1) && (__PIC__ != 2)
|
||||
#error "unexpected __PIC__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__pic__)
|
||||
#if (__pic__ != 1) && (__pic__ != 2)
|
||||
#error "unexpected __pic__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIE__) && defined(__pie__)
|
||||
#if (__PIE__ + 0) != (__pie__ + 0)
|
||||
#error "unexpected __PIE__ vs __pie__ mismatch"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIE__)
|
||||
#if (__PIE__ != 1) && (__PIE__ != 2)
|
||||
#error "unexpected __PIE__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__pie__)
|
||||
#if (__pie__ != 1) && (__pie__ != 2)
|
||||
#error "unexpected __pie__ value"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "system_check_predefs.h"
|
||||
|
||||
#if !defined(_FILE_OFFSET_BITS)
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
@@ -41,6 +43,13 @@
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#if defined(__PTRADDR_TYPE__) && !defined(__SIZEOF_PTRADDR_T__)
|
||||
#if !defined(__PTRADDR_WIDTH__)
|
||||
#error "missing __PTRADDR_WIDTH__"
|
||||
#endif
|
||||
#define __SIZEOF_PTRADDR_T__ (__PTRADDR_WIDTH__ / 8)
|
||||
#endif
|
||||
|
||||
#if !defined(__USE_MINGW_ANSI_STDIO)
|
||||
#if defined(_WIN32) && defined(__MINGW32__) && (defined(__clang__) || defined(__GNUC__))
|
||||
#define __USE_MINGW_ANSI_STDIO 1
|
||||
|
||||
+10
-56
@@ -33,62 +33,6 @@
|
||||
#error "FATAL ERROR: C++17 is required"
|
||||
#endif
|
||||
|
||||
// check expected defines
|
||||
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN64__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(__MINGW32__)
|
||||
#error "missing __MINGW32__"
|
||||
#endif
|
||||
#if defined(_WIN64) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
|
||||
// byte order - these are pre-defined since gcc-4.6 (2011) and clang-3.2 (2012)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_LITTLE_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_LITTLE_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER__) || (__BYTE_ORDER__ + 0 == 0)
|
||||
#error "missing __BYTE_ORDER__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 != 4321)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 != 1234)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
|
||||
#error "unexpected __BYTE_ORDER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// pic and pie
|
||||
#if defined(__PIC__) && defined(__pic__)
|
||||
static_assert((__PIC__) == (__pic__));
|
||||
#endif
|
||||
#if defined(__PIC__)
|
||||
static_assert(__PIC__ == 1 || __PIC__ == 2);
|
||||
#endif
|
||||
#if defined(__pic__)
|
||||
static_assert(__pic__ == 1 || __pic__ == 2);
|
||||
#endif
|
||||
#if defined(__PIE__) && defined(__pie__)
|
||||
static_assert((__PIE__) == (__pie__));
|
||||
#endif
|
||||
#if defined(__PIE__)
|
||||
static_assert(__PIE__ == 1 || __PIE__ == 2);
|
||||
#endif
|
||||
#if defined(__pie__)
|
||||
static_assert(__pie__ == 1 || __pie__ == 2);
|
||||
#endif
|
||||
|
||||
// sanity checks
|
||||
#if defined(_ILP32) || defined(__ILP32) || defined(__ILP32__)
|
||||
static_assert(sizeof(int) == 4);
|
||||
@@ -98,8 +42,14 @@ static_assert(sizeof(void *) == 4);
|
||||
#if defined(_LP64) || defined(__LP64) || defined(__LP64__)
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) == 8);
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__) && (__SIZEOF_POINTER__ == 16)
|
||||
// CHERI BUG/FEATURE: obviously CHERI should *NOT* pre-define __LP64__ on P128, but
|
||||
// maybe they do this for porting/compatibility reasons...
|
||||
static_assert(sizeof(void *) == 16);
|
||||
#else
|
||||
static_assert(sizeof(void *) == 8);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) == 4);
|
||||
@@ -151,6 +101,7 @@ static_assert(sizeof(void *) == sizeof(long));
|
||||
#include <bit>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
@@ -193,6 +144,9 @@ static_assert(sizeof(void *) == sizeof(long));
|
||||
!defined(__GNUC__)
|
||||
#undef WITH_VALGRIND
|
||||
#endif
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
#undef WITH_VALGRIND
|
||||
#endif
|
||||
#if WITH_VALGRIND
|
||||
#include <valgrind/include/valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
+46
-8
@@ -25,6 +25,7 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#define WANT_WINDOWS_LEAN_H 1
|
||||
#include "system_headers.h"
|
||||
#define ACC_WANT_ACC_INCI_H 1
|
||||
#include "miniacc.h"
|
||||
@@ -291,23 +292,24 @@ void *upx_calloc(size_t n, size_t element_size) may_throw {
|
||||
}
|
||||
|
||||
// simple unoptimized memswap()
|
||||
void upx_memswap(void *a, void *b, size_t bytes) noexcept {
|
||||
if (a != b && bytes != 0) {
|
||||
byte *x = (byte *) a;
|
||||
byte *y = (byte *) b;
|
||||
// TODO later: CHERI clang bug/miscompilation with upx_memswap() ???
|
||||
void upx_memswap(void *aa, void *bb, size_t bytes) noexcept {
|
||||
if (aa != bb && bytes != 0) {
|
||||
byte *a = (byte *) aa;
|
||||
byte *b = (byte *) bb;
|
||||
do {
|
||||
// strange clang-analyzer-15 false positive when compiling in Debug mode
|
||||
// clang-analyzer-core.uninitialized.Assign
|
||||
byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
||||
*x++ = *y;
|
||||
*y++ = tmp;
|
||||
byte tmp = *a; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
||||
*a++ = *b;
|
||||
*b++ = tmp;
|
||||
} while (--bytes != 0);
|
||||
}
|
||||
}
|
||||
|
||||
// much better memswap(), optimized for our use case in sort functions below
|
||||
static inline void memswap_no_overlap(byte *a, byte *b, size_t bytes) noexcept {
|
||||
#if defined(__clang__) && __clang_major__ < 15
|
||||
#if defined(__clang__) && (__clang_major__ < 15) && !defined(__CHERI__)
|
||||
// work around a clang < 15 ICE (Internal Compiler Error)
|
||||
// @COMPILER_BUG @CLANG_BUG
|
||||
upx_memswap(a, b, bytes);
|
||||
@@ -418,6 +420,42 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("upx_memswap") {
|
||||
auto check4 = [](int off1, int off2, int len, int a, int b, int c, int d) {
|
||||
byte p[4] = {0, 1, 2, 3};
|
||||
assert_noexcept(a + b + c + d == 0 + 1 + 2 + 3);
|
||||
upx_memswap(p + off1, p + off2, len);
|
||||
CHECK((p[0] == a && p[1] == b && p[2] == c && p[3] == d));
|
||||
};
|
||||
// identical
|
||||
check4(0, 0, 4, 0, 1, 2, 3);
|
||||
// non-overlapping
|
||||
check4(0, 1, 1, 1, 0, 2, 3);
|
||||
check4(1, 0, 1, 1, 0, 2, 3);
|
||||
check4(0, 2, 2, 2, 3, 0, 1);
|
||||
check4(2, 0, 2, 2, 3, 0, 1);
|
||||
// overlapping
|
||||
check4(0, 1, 2, 1, 2, 0, 3);
|
||||
check4(1, 0, 2, 1, 2, 0, 3);
|
||||
check4(0, 1, 3, 1, 2, 3, 0);
|
||||
check4(1, 0, 3, 1, 2, 3, 0);
|
||||
|
||||
// pointer array
|
||||
{
|
||||
typedef byte element_type;
|
||||
element_type a = 11, b = 22;
|
||||
element_type *array[4];
|
||||
memset(array, 0xfb, sizeof(array));
|
||||
array[1] = &a;
|
||||
array[3] = &b;
|
||||
upx_memswap(array, array + 2, 2 * sizeof(array[0]));
|
||||
assert(array[1] == &b);
|
||||
assert(array[3] == &a);
|
||||
assert(*array[1] == 22);
|
||||
assert(*array[3] == 11);
|
||||
}
|
||||
}
|
||||
|
||||
#if UPX_CONFIG_USE_STABLE_SORT
|
||||
// instantiate function templates for all element sizes we need; efficient
|
||||
// run-time, but code size bloat (about 4KiB code size for each function
|
||||
|
||||
+24
-5
@@ -93,9 +93,23 @@ T *NewArray(upx_uint64_t n) may_throw {
|
||||
// ptr util
|
||||
**************************************************************************/
|
||||
|
||||
// TODO later: CHERI; see cheri_address_get()
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
forceinline upx_ptraddr_t ptr_get_address(const void *p) noexcept {
|
||||
return __builtin_cheri_address_get(p);
|
||||
}
|
||||
forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) noexcept {
|
||||
return __builtin_cheri_address_get(p);
|
||||
}
|
||||
#else
|
||||
forceinline upx_ptraddr_t ptr_get_address(const void *p) noexcept { return (upx_uintptr_t) p; }
|
||||
forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) noexcept { return p; }
|
||||
#endif
|
||||
|
||||
template <size_t Alignment>
|
||||
forceinline bool ptr_is_aligned(const void *p) noexcept {
|
||||
static_assert(upx::has_single_bit(Alignment));
|
||||
return (ptr_get_address(p) & (Alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
// ptrdiff_t with nullptr checks and asserted size; will throw on failure
|
||||
// NOTE: returns size_in_bytes, not number of elements!
|
||||
@@ -138,10 +152,15 @@ forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *
|
||||
// - this should play nice with static analyzers like clang-tidy etc.
|
||||
// NOTE: this is clearly UB (Undefined Behaviour), and stricter compilers or
|
||||
// architectures may need a more advanced/costly implementation in the future
|
||||
// TODO later: CHERI
|
||||
template <class T>
|
||||
inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
||||
ptr = (T *) (void *) 251; // 0x000000fb // NOLINT(performance-no-int-to-ptr)
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
// TODO later: examine __builtin_cheri_bounds_set()
|
||||
ptr = upx::ptr_static_cast<T *>(&ptr); // FIXME: HACK: point to address of self
|
||||
#else
|
||||
// pretend there is some memory-mapped I/O at address 0x00000200
|
||||
ptr = (T *) (void *) 512; // NOLINT(performance-no-int-to-ptr)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@@ -152,7 +171,7 @@ noinline void *upx_calloc(size_t n, size_t element_size) may_throw;
|
||||
|
||||
noinline const char *upx_getenv(const char *envvar) noexcept;
|
||||
|
||||
void upx_memswap(void *a, void *b, size_t bytes) noexcept;
|
||||
noinline void upx_memswap(void *a, void *b, size_t bytes) noexcept;
|
||||
|
||||
noinline void upx_rand_init(void) noexcept;
|
||||
noinline int upx_rand(void) noexcept;
|
||||
@@ -174,7 +193,7 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare);
|
||||
#define upx_qsort(a, n, element_size, compare) \
|
||||
upx_std_stable_sort<(element_size)>((a), (n), (compare))
|
||||
#else
|
||||
// use libc qsort(); good enough for our use cases
|
||||
// use libc qsort(); good enough for our use cases
|
||||
#define upx_qsort ::qsort
|
||||
#endif
|
||||
|
||||
|
||||
@@ -49,4 +49,19 @@
|
||||
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
#error "unexpected _WIN64"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
// #error "unexpected _WIN64"
|
||||
#undef _WIN64
|
||||
#endif
|
||||
|
||||
@@ -207,7 +207,7 @@ public: // raw access
|
||||
pointer raw_bytes(size_t bytes) const {
|
||||
assertInvariants();
|
||||
if (bytes > 0) {
|
||||
if __acc_cte (ptr == nullptr)
|
||||
if very_unlikely (ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
}
|
||||
return ptr;
|
||||
|
||||
Reference in New Issue
Block a user