diff --git a/.clang-format b/.clang-format index 5b93ff42..137b7a62 100644 --- a/.clang-format +++ b/.clang-format @@ -18,6 +18,8 @@ AttributeMacros: - __acc_noinline - __acc_static_noinline - __acc_static_forceinline + - forceinline + - noinline EmptyLineBeforeAccessModifier: Leave SortIncludes: false SpaceAfterCStyleCast: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc3a4e7b..fb9b547a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,15 +54,15 @@ jobs: fail-fast: false matrix: include: - - { os: ubuntu-20.04, use_m32: false } - { os: ubuntu-22.04, use_m32: true } + - { os: ubuntu-20.04, use_m32: false } steps: - - name: 'Install extra 32-bit packages' + - name: 'Install extra 32-bit and Windows packages' if: ${{ matrix.use_m32 }} run: | sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y gcc-multilib g++-multilib + sudo apt-get install -y g++-multilib g++-mingw-w64-i686 g++-mingw-w64-x86-64 - name: 'Check out code' uses: actions/checkout@v3 with: { submodules: true } @@ -82,11 +82,17 @@ jobs: - name: 'Build cmake extra/gcc-m32/release' if: ${{ matrix.use_m32 }} run: 'make build/extra/gcc-m32/release' + - name: 'Build cmake extra/cross-windows-mingw32/release' + if: ${{ matrix.use_m32 }} + run: 'make build/extra/cross-windows-mingw32/release' + - name: 'Build cmake extra/cross-windows-mingw64/release' + if: ${{ matrix.use_m32 }} + run: 'make build/extra/cross-windows-mingw64/release' - name: 'Make artifact' run: | N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }} mkdir -p "tmp/artifact/$N" - (cd build/extra && cp -ai --parents */*/upx "../../tmp/artifact/$N") + (cd build && shopt -s nullglob && cp -ai --parents */upx{,.exe} */*/*/upx{,.exe} "../tmp/artifact/$N") (cd tmp/artifact && tar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N") # GitHub Actions magic: set "artifact_name" environment value for use in next step echo "artifact_name=$N" >> $GITHUB_ENV @@ -121,8 +127,7 @@ jobs: matrix: include: - { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true } - # { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true } # disable gcc - XCode 14.0.1 ld bug; supposed to be fixed in 14.1 - - { os: macos-12, testsuite: true } + - { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true } steps: - name: 'Install brew packages' if: ${{ matrix.testsuite }} @@ -145,11 +150,15 @@ jobs: - name: 'Build cmake extra/gcc/release' if: ${{ matrix.gcc != '' }} run: 'make build/extra/gcc/release CC=${{ matrix.gcc }} CXX=${{ matrix.gxx }}' + - name: 'Build cmake xtarget/cross-darwin-arm64/release' + run: | + export CC="clang -target arm64-apple-darwin" CXX="clang++ -target arm64-apple-darwin" + make UPX_XTARGET=cross-darwin-arm64 - name: 'Make artifact' run: | N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }} mkdir -p "tmp/artifact/$N" - (cd build/extra && rsync -R -a */*/upx "../../tmp/artifact/$N/") + (cd build && rsync -R -a */*/*/upx "../tmp/artifact/$N/") (cd tmp/artifact && gtar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N") # GitHub Actions magic: set "artifact_name" environment value for use in next step echo "artifact_name=$N" >> $GITHUB_ENV @@ -325,14 +334,17 @@ jobs: needs: [ job-rebuild-and-verify-stubs ] name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }} runs-on: ubuntu-latest + ##container: alpine:3.17 # older versions such as alpine:3.12 also work; no-container also works strategy: fail-fast: false matrix: include: + - { zig_target: aarch64-linux-musl } - { zig_target: aarch64-macos.11-none } - { zig_target: aarch64-macos.12-none } - { zig_target: aarch64-macos.13-none } - { zig_target: aarch64-windows-gnu } + - { zig_target: i386-linux-musl } - { zig_target: i386-windows-gnu } - { zig_target: x86_64-linux-musl } - { zig_target: x86_64-linux-musl, zig_pic: -fPIE } @@ -341,18 +353,28 @@ jobs: - { zig_target: x86_64-macos.13-none } - { zig_target: x86_64-windows-gnu } env: - # 2023-01-22 - ZIG_DIST_VERSION: 0.11.0-dev.1413+a51c76541 + # 2023-01-24 + ZIG_DIST_VERSION: 0.11.0-dev.1436+59d9afcb5 # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} ZIG_PIC: ${{ matrix.zig_pic }} ZIG_TARGET: ${{ matrix.zig_target }} steps: + - name: 'Install Alpine packages' + if: ${{ job.container }} + shell: sh + run: | + apk update && apk upgrade && apk add bash cmake file git make tar xz + # set PATH like in Ubuntu + echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV + # this seems to be needed when running in a container (beause of UID mismatch??) + git config --global --add safe.directory '*' - name: 'Check out code' uses: actions/checkout@v3 with: { submodules: true } - name: ${{ format('Install Zig {0}', env.ZIG_DIST_VERSION) }} + shell: bash run: | # GitHub Actions magic: set "UPX_GITREV_SHORT" environment value for use in steps below rev=$(git rev-parse --short=7 HEAD) @@ -392,11 +414,12 @@ jobs: cmake ../../../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_AR=$HOME/.local/bin/zig-ar -DCMAKE_C_COMPILER=zig-cc -DCMAKE_CXX_COMPILER=zig-cxx -DCMAKE_RANLIB=$HOME/.local/bin/zig-ranlib $EXTRA_CMAKE_CONFIG_FLAGS_DEBUG cmake --build . --config Debug --parallel --verbose file ./upx* - - name: ${{ format('Make artifact from upx-{0}-{1}', env.GITHUB_REF_NAME, env.UPX_GITREV_SHORT) }} + - name: ${{ format('Make artifact from upx-{0}-{1}', github.ref_name, env.UPX_GITREV_SHORT) }} + shell: bash run: | N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-zigcc-${{ matrix.zig_target }}${ZIG_PIC} mkdir -p "tmp/artifact/$N" - (cd build && shopt -s nullglob && cp -ai --parents */upx* zig/*/*/upx* "../tmp/artifact/$N") + (cd build && shopt -s nullglob && cp -ai --parents */upx{,.exe} */*/*/upx{,.exe} "../tmp/artifact/$N") (cd tmp/artifact && tar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N") # GitHub Actions magic: set "artifact_name" environment value for use in next step echo "artifact_name=$N" >> $GITHUB_ENV diff --git a/Makefile b/Makefile index eaaaf8b9..f03c2757 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # mkdir -p build/release # cd build/release # cmake ../.. -# cmake --build . +# cmake --build . --parallel # (or just use "make -j" instead) CMAKE = cmake UPX_CMAKE_BUILD_FLAGS += --parallel @@ -44,6 +44,7 @@ release: build/release .PHONY: PHONY .NOTPARALLEL: # because the actual builds use "cmake --parallel" +.SUFFIXES: #*********************************************************************** # extra builds: some pre-defined build configurations @@ -133,18 +134,42 @@ build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@ build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ -# advanced: generic eXtra target; usage: +# cross compiler: macOS arm64 +build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug) +build/extra/cross-darwin-arm64/release: PHONY; $(call run_config_and_build,$@,Release) +build/extra/cross-darwin-arm64/%: export CC = clang -target arm64-apple-darwin +build/extra/cross-darwin-arm64/%: export CXX = clang++ -target arm64-apple-darwin + +# cross compiler: macOS x86_64 +build/extra/cross-darwin-x86_64/debug: PHONY; $(call run_config_and_build,$@,Debug) +build/extra/cross-darwin-x86_64/release: PHONY; $(call run_config_and_build,$@,Release) +build/extra/cross-darwin-x86_64/%: export CC = clang -target x86_64-apple-darwin +build/extra/cross-darwin-x86_64/%: export CXX = clang++ -target x86_64-apple-darwin + +#*********************************************************************** +# advanced: generic eXtra target +#*********************************************************************** + +# usage: # make UPX_XTARGET=mytarget CC="my-cc -flags" CXX="my-cxx -flags" -# make UPX_XTARGET=mytarget CC="my-cc -flags" CXX="my-cxx -flags" build/xtarget/mytarget/debug +# make UPX_XTARGET=mytarget CC="my-cc -flags" CXX="my-cxx -flags" xtarget/debug + ifneq ($(UPX_XTARGET),) ifneq ($(CC),) ifneq ($(CXX),) + UPX_XTARGET := $(UPX_XTARGET) -$(eval .DEFAULT_GOAL = build/xtarget/$(UPX_XTARGET)/release) build/xtarget/$(UPX_XTARGET)/debug: PHONY; $(call run_config_and_build,$@,Debug) build/xtarget/$(UPX_XTARGET)/release: PHONY; $(call run_config_and_build,$@,Release) build/xtarget/$(UPX_XTARGET)/%: export CC build/xtarget/$(UPX_XTARGET)/%: export CXX +# shortcuts +xtarget/debug: build/xtarget/$(UPX_XTARGET)/debug +xtarget/release: build/xtarget/$(UPX_XTARGET)/release +# set new default +.DEFAULT_GOAL = xtarget/release +##$(eval .DEFAULT_GOAL = build/xtarget/$(UPX_XTARGET)/release) + endif endif endif diff --git a/src/bele.h b/src/bele.h index 21831709..36d9ae60 100644 --- a/src/bele.h +++ b/src/bele.h @@ -38,35 +38,35 @@ // core - NE **************************************************************************/ -__acc_static_forceinline unsigned get_ne16(const void *p) { +static forceinline unsigned get_ne16(const void *p) { upx_uint16_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } -__acc_static_forceinline unsigned get_ne32(const void *p) { +static forceinline unsigned get_ne32(const void *p) { upx_uint32_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } -__acc_static_forceinline upx_uint64_t get_ne64(const void *p) { +static forceinline upx_uint64_t get_ne64(const void *p) { upx_uint64_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } -__acc_static_forceinline void set_ne16(void *p, unsigned vv) { +static forceinline void set_ne16(void *p, unsigned vv) { upx_uint16_t v = (upx_uint16_t) (vv & 0xffff); upx_memcpy_inline(p, &v, sizeof(v)); } -__acc_static_forceinline void set_ne32(void *p, unsigned vv) { +static forceinline void set_ne32(void *p, unsigned vv) { upx_uint32_t v = vv; upx_memcpy_inline(p, &v, sizeof(v)); } -__acc_static_forceinline void set_ne64(void *p, upx_uint64_t vv) { +static forceinline void set_ne64(void *p, upx_uint64_t vv) { upx_uint64_t v = vv; upx_memcpy_inline(p, &v, sizeof(v)); } @@ -79,34 +79,31 @@ __acc_static_forceinline void set_ne64(void *p, upx_uint64_t vv) { ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) -__acc_static_forceinline unsigned bswap16(unsigned v) { - return (unsigned) _byteswap_ulong(v << 16); -} -__acc_static_forceinline unsigned bswap32(unsigned v) { return (unsigned) _byteswap_ulong(v); } -__acc_static_forceinline upx_uint64_t bswap64(upx_uint64_t v) { return _byteswap_uint64(v); } +// unfortunately *not* constexpr with MSVC +static forceinline unsigned bswap16(unsigned v) { return (unsigned) _byteswap_ulong(v << 16); } +static forceinline unsigned bswap32(unsigned v) { return (unsigned) _byteswap_ulong(v); } +static forceinline upx_uint64_t bswap64(upx_uint64_t v) { return _byteswap_uint64(v); } #else -__acc_static_forceinline constexpr unsigned bswap16(unsigned v) { +static forceinline constexpr unsigned bswap16(unsigned v) { // return __builtin_bswap16((upx_uint16_t) (v & 0xffff)); // return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48); return __builtin_bswap32(v << 16); } -__acc_static_forceinline constexpr unsigned bswap32(unsigned v) { +static forceinline constexpr unsigned bswap32(unsigned v) { // return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32); return __builtin_bswap32(v); } -__acc_static_forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) { - return __builtin_bswap64(v); -} +static forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) { return __builtin_bswap64(v); } #endif -__acc_static_forceinline constexpr unsigned no_bswap16(unsigned v) { +static forceinline constexpr unsigned no_bswap16(unsigned v) { return v & 0xffff; // needed so that this is equivalent to bswap16() above } -__acc_static_forceinline constexpr unsigned no_bswap32(unsigned v) { return v; } -__acc_static_forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) { return v; } +static forceinline constexpr unsigned no_bswap32(unsigned v) { return v; } +static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) { return v; } #if (ACC_ABI_BIG_ENDIAN) #define ne16_to_be16(v) no_bswap16(v) @@ -186,14 +183,14 @@ inline void set_le26(void *p, unsigned v) { // get signed values **************************************************************************/ -__acc_static_forceinline int sign_extend(unsigned v, unsigned bits) { +static forceinline int sign_extend(unsigned v, unsigned bits) { const unsigned sign_bit = 1u << (bits - 1); v &= sign_bit | (sign_bit - 1); v |= 0 - (v & sign_bit); return ACC_ICAST(int, v); } -__acc_static_forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) { +static forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) { const upx_uint64_t sign_bit = 1ull << (bits - 1); v &= sign_bit | (sign_bit - 1); v |= 0 - (v & sign_bit); @@ -599,15 +596,15 @@ inline T *operator-(T *ptr, const LE32 &v) { return ptr - unsigned(v); } -// these are not implemented on purpose and will cause link-time errors +// these are not implemented on purpose and will cause errors template -T *operator+(T *ptr, const BE64 &v); +T *operator+(T *ptr, const BE64 &v) DELETED_FUNCTION; template -T *operator-(T *ptr, const BE64 &v); +T *operator-(T *ptr, const BE64 &v) DELETED_FUNCTION; template -T *operator+(T *ptr, const LE64 &v); +T *operator+(T *ptr, const LE64 &v) DELETED_FUNCTION; template -T *operator-(T *ptr, const LE64 &v); +T *operator-(T *ptr, const LE64 &v) DELETED_FUNCTION; /************************************************************************* // global overloads diff --git a/src/check/dt_xspan.cpp b/src/check/dt_xspan.cpp index 3ca7e36e..f41b5590 100644 --- a/src/check/dt_xspan.cpp +++ b/src/check/dt_xspan.cpp @@ -29,7 +29,34 @@ #include "../conf.h" /************************************************************************* -// basic +// raw_bytes +**************************************************************************/ + +TEST_CASE("raw_bytes ptr") { + upx_uint32_t *ptr = nullptr; + CHECK_NOTHROW(raw_bytes(ptr, 0)); + CHECK_THROWS(raw_bytes(ptr, 1)); + CHECK_THROWS(raw_index_bytes(ptr, 0, 0)); + CHECK_THROWS(raw_index_bytes(ptr, 1, 0)); + CHECK_THROWS(raw_index_bytes(ptr, 0, 1)); + upx_uint32_t buf[4]; + ptr = buf; + CHECK(ptr_udiff_bytes(raw_index_bytes(ptr, 1, 1), ptr) == 4u); +} + +TEST_CASE("raw_bytes bounded array") { + upx_uint32_t buf[4]; + CHECK_NOTHROW(raw_bytes(buf, 16)); + CHECK_THROWS(raw_bytes(buf, 17)); + CHECK_NOTHROW(raw_index_bytes(buf, 4, 0)); + CHECK_THROWS(raw_index_bytes(buf, 4, 1)); + CHECK_NOTHROW(raw_index_bytes(buf, 3, 4)); + CHECK_THROWS(raw_index_bytes(buf, 3, 5)); + CHECK(ptr_udiff_bytes(raw_index_bytes(buf, 1, 1), buf) == 4u); +} + +/************************************************************************* +// basic xspan **************************************************************************/ TEST_CASE("basic xspan usage") { diff --git a/src/conf.h b/src/conf.h index 70eb5c79..d8c340ff 100644 --- a/src/conf.h +++ b/src/conf.h @@ -149,6 +149,12 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char #undef NDEBUG #include +// C++20 std::is_bounded_array +template +struct std_is_bounded_array : public std::false_type {}; +template +struct std_is_bounded_array : public std::true_type {}; + /************************************************************************* // core @@ -185,6 +191,24 @@ typedef upx_int64_t upx_off_t; #define off_t upx_off_t #endif +// shortcuts +#define forceinline __acc_forceinline +#if _MSC_VER +#define noinline __declspec(noinline) +#undef __acc_noinline +#define __acc_noinline noinline +#else +#define noinline __acc_noinline +#endif +#define likely __acc_likely +#define unlikely __acc_unlikely +#define very_likely __acc_very_likely +#define very_unlikely __acc_very_unlikely + +#define COMPILE_TIME_ASSERT(e) ACC_COMPILE_TIME_ASSERT(e) +#define DELETED_FUNCTION = delete +#define UNUSED(var) ACC_UNUSED(var) + /************************************************************************* // portab @@ -341,19 +365,16 @@ inline void NO_fprintf(FILE *, const char *, ...) {} # define upx_return_address() nullptr #endif -#define UNUSED(var) ACC_UNUSED(var) -#define COMPILE_TIME_ASSERT(e) ACC_COMPILE_TIME_ASSERT(e) - // 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() }; #if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__) // horrible hack for broken compiler -#define upx_alignas_1 __attribute__((__aligned__(1),__packed__)) -#define upx_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ??? -#define upx_alignas__(a) upx_alignas_ ## a -#define alignas(x) upx_alignas__(x) +#define upx_fake_alignas_1 __attribute__((__aligned__(1),__packed__)) +#define upx_fake_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ??? +#define upx_fake_alignas__(a) upx_fake_alignas_ ## a +#define alignas(x) upx_fake_alignas__(x) #endif #define COMPILE_TIME_ASSERT_ALIGNOF_USING_SIZEOF__(a,b) { \ @@ -385,7 +406,7 @@ inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b; template struct USizeOfTypeImpl { - __acc_static_forceinline constexpr unsigned value() { + static forceinline constexpr unsigned value() { COMPILE_TIME_ASSERT(TypeSize >= 1 && TypeSize <= 64 * 1024); // arbitrary limit return ACC_ICONV(unsigned, TypeSize); } @@ -408,8 +429,10 @@ protected: inline noncopyable() {} inline ~noncopyable() {} private: - noncopyable(const noncopyable &); // undefined - const noncopyable& operator=(const noncopyable &); // undefined + noncopyable(const noncopyable &) DELETED_FUNCTION; // copy constuctor + noncopyable& operator=(const noncopyable &) DELETED_FUNCTION; // copy assignment + noncopyable(noncopyable &&) DELETED_FUNCTION; // move constructor + noncopyable& operator=(noncopyable &&) DELETED_FUNCTION; // move assignment }; @@ -630,25 +653,26 @@ struct OptVar assertValue(v); } - OptVar() : v(default_value), is_set(0) { } + OptVar() : v(default_value), is_set(false) { } OptVar& operator= (const T &other) { - v = other; is_set = 1; - assertValue(); + assertValue(other); + v = other; + is_set = true; return *this; } - void reset() { v = default_value; is_set = 0; } + void reset() { v = default_value; is_set = false; } operator T () const { return v; } T v; - unsigned is_set; + bool is_set; }; // optional assignments template inline void oassign(OptVar &self, const OptVar &other) { - if (other.is_set) { self.v = other.v; self.is_set = 1; } + if (other.is_set) { self.v = other.v; self.is_set = true; } } template inline void oassign(T &v, const OptVar &other) { @@ -855,32 +879,6 @@ int upx_test_overlap ( const upx_bytep buf, 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 -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; -} - -// default: for any regular pointer, raw_index_bytes() is just "pointer + index" -// NOTE: index == number of elements, *NOT* size in bytes! -template -inline T *raw_index_bytes(T *ptr, size_t index, size_t size_in_bytes) { - typedef T element_type; - return raw_bytes(ptr, mem_size(sizeof(element_type), index, size_in_bytes)) + index; -} - #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) # error "something pulled in " diff --git a/src/util/bptr.h b/src/util/bptr.h index 1d17626b..3fe4a334 100644 --- a/src/util/bptr.h +++ b/src/util/bptr.h @@ -109,14 +109,14 @@ public: private: void checkNULL() const { - if __acc_very_unlikely (!ptr_) + if very_unlikely (!ptr_) throwCantUnpack("unexpected NULL pointer; take care!"); } - __acc_forceinline void checkRange() const { checkRange(ptr_, base_, size_in_bytes_); } - __acc_forceinline void checkRange(const void *p) const { checkRange(p, base_, size_in_bytes_); } + forceinline void checkRange() const { checkRange(ptr_, base_, size_in_bytes_); } + forceinline void checkRange(const void *p) const { checkRange(p, base_, size_in_bytes_); } static void checkRange(const void *ptr, const void *base, size_t size_in_bytes) { size_t off = (const char *) ptr - (const char *) base; - if __acc_very_unlikely (off > size_in_bytes) + if very_unlikely (off > size_in_bytes) throwCantUnpack("pointer out of range; take care!"); } void check() const { // check ptr_ invariant: either NULL or valid checkRange() diff --git a/src/util/membuffer.cpp b/src/util/membuffer.cpp index 0a0db6ce..5a94f5bc 100644 --- a/src/util/membuffer.cpp +++ b/src/util/membuffer.cpp @@ -32,7 +32,7 @@ void *membuffer_get_void_ptr(MemBuffer &mb) { return mb.getVoidPtr(); } unsigned membuffer_get_size(MemBuffer &mb) { return mb.getSize(); } -MemBuffer::Stats MemBuffer::stats; +/*static*/ MemBuffer::Stats MemBuffer::stats; #if DEBUG #define debug_set(var, expr) (var) = (expr) @@ -45,23 +45,23 @@ MemBuffer::Stats MemBuffer::stats; **************************************************************************/ #if defined(__SANITIZE_ADDRESS__) -__acc_static_forceinline constexpr bool use_simple_mcheck() { return false; } +static forceinline constexpr bool use_simple_mcheck() { return false; } #elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND) static int use_simple_mcheck_flag = -1; -__acc_static_noinline void use_simple_mcheck_init() { +static noinline void use_simple_mcheck_init() { use_simple_mcheck_flag = 1; if (RUNNING_ON_VALGRIND) { use_simple_mcheck_flag = 0; // fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n"); } } -__acc_static_forceinline bool use_simple_mcheck() { - if __acc_unlikely (use_simple_mcheck_flag < 0) +static forceinline bool use_simple_mcheck() { + if very_unlikely (use_simple_mcheck_flag < 0) use_simple_mcheck_init(); return (bool) use_simple_mcheck_flag; } #else -__acc_static_forceinline constexpr bool use_simple_mcheck() { return true; } +static forceinline constexpr bool use_simple_mcheck() { return true; } #endif /************************************************************************* @@ -119,12 +119,14 @@ 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) { - unsigned const z = uncompressed_size; // fewer keystrokes and display columns - unsigned const w = umax(8, width(z - 1)); // ignore tiny offsets + if (uncompressed_size == 0) + throwCantPack("invalid uncompressed_size"); + const unsigned z = uncompressed_size; // fewer keystrokes and display columns + const unsigned 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); + bytes = umax(bytes, z + z / 8); // NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11") bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8); // NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12") @@ -133,21 +135,28 @@ unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned e bytes = umax(bytes, z + (z >> 8) + ((z < (128 << 10)) ? (((128 << 10) - z) >> 11) : 0)); // extra + 256 safety for rounding bytes = mem_size(1, bytes, extra, 256); + UNUSED(w); return bytes; } unsigned MemBuffer::getSizeForDecompression(unsigned uncompressed_size, unsigned extra) { + if (uncompressed_size == 0) + throwCantPack("invalid uncompressed_size"); size_t bytes = mem_size(1, uncompressed_size, extra); // check return ACC_ICONV(unsigned, bytes); } void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) { + if (uncompressed_size == 0) + throwCantPack("invalid uncompressed_size"); unsigned size = getSizeForCompression(uncompressed_size, extra); alloc(size); debug_set(debug.last_return_address_alloc, upx_return_address()); } void MemBuffer::allocForDecompression(unsigned uncompressed_size, unsigned extra) { + if (uncompressed_size == 0) + throwCantPack("invalid uncompressed_size"); unsigned size = getSizeForDecompression(uncompressed_size, extra); alloc(size); debug_set(debug.last_return_address_alloc, upx_return_address()); @@ -254,6 +263,10 @@ TEST_CASE("MemBuffer") { CHECK(raw_bytes(mb, 64) != nullptr); CHECK(raw_bytes(mb, 64) == mb.getVoidPtr()); CHECK_THROWS(raw_bytes(mb, 65)); + CHECK_NOTHROW(mb + 64); + CHECK_NOTHROW(64 + mb); + CHECK_THROWS(mb + 65); + CHECK_THROWS(65 + mb); if (use_simple_mcheck()) { upx_byte *b = raw_bytes(mb, 0); unsigned magic1 = get_ne32(b - 4); @@ -264,4 +277,14 @@ TEST_CASE("MemBuffer") { } } +TEST_CASE("MemBuffer::getSizeForCompression") { + CHECK_THROWS(MemBuffer::getSizeForCompression(0)); + CHECK_THROWS(MemBuffer::getSizeForDecompression(0)); + CHECK(MemBuffer::getSizeForCompression(1) == 320); + CHECK(MemBuffer::getSizeForCompression(256) == 576); + CHECK(MemBuffer::getSizeForCompression(1024) == 1408); + // CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 0); // TODO + // CHECK(MemBuffer::getSizeForCompression(UPX_RSIZE_MAX) == 0); // TODO +} + /* vim:set ts=4 sw=4 et: */ diff --git a/src/util/membuffer.h b/src/util/membuffer.h index 68fbcaf4..65f1b678 100644 --- a/src/util/membuffer.h +++ b/src/util/membuffer.h @@ -40,31 +40,34 @@ public: typedef typename std::add_pointer::type pointer; protected: - pointer b = nullptr; - unsigned b_size_in_bytes = 0; + pointer b; + unsigned b_size_in_bytes; public: + MemBufferBase() : b(nullptr), b_size_in_bytes(0) {} + // NOTE: implicit conversion to underlying pointer // NOTE: for fully bound-checked pointer use XSPAN_S from xspan.h operator pointer() const { return b; } - template ::value, U>::type> - pointer operator+(U n) const { + template + typename std::enable_if::value, pointer>::type operator+(U n) const { size_t bytes = mem_size(sizeof(T), n); // check mem_size return raw_bytes(bytes) + n; // and check bytes } +private: // NOT allowed; use raw_bytes() instead - template ::value, U>::type> - pointer operator-(U n) const = delete; + template + typename std::enable_if::value, pointer>::type + operator-(U n) const DELETED_FUNCTION; +public: pointer raw_bytes(size_t bytes) const { if (bytes > 0) { - if __acc_very_unlikely (b == nullptr) + if very_unlikely (b == nullptr) throwInternalError("MemBuffer raw_bytes unexpected NULL ptr"); - if __acc_very_unlikely (bytes > b_size_in_bytes) + if very_unlikely (bytes > b_size_in_bytes) throwInternalError("MemBuffer raw_bytes invalid size"); } return b; @@ -73,7 +76,7 @@ public: class MemBuffer final : public MemBufferBase { public: - MemBuffer() = default; + MemBuffer() : MemBufferBase() {} explicit MemBuffer(upx_uint64_t size_in_bytes); ~MemBuffer(); @@ -94,14 +97,14 @@ public: // util void fill(unsigned off, unsigned len, int value); - __acc_forceinline void clear(unsigned off, unsigned len) { fill(off, len, 0); } - __acc_forceinline void clear() { fill(0, b_size_in_bytes, 0); } + forceinline void clear(unsigned off, unsigned len) { fill(off, len, 0); } + forceinline void clear() { fill(0, b_size_in_bytes, 0); } // If the entire range [skip, skip+take) is inside the buffer, // then return &b[skip]; else throwCantPack(sprintf(errfmt, skip, take)). // This is similar to BoundedPtr, except only checks once. // skip == offset, take == size_in_bytes - __acc_forceinline pointer subref(const char *errfmt, size_t skip, size_t take) { + forceinline pointer subref(const char *errfmt, size_t skip, size_t take) { return (pointer) subref_impl(errfmt, skip, take); } @@ -118,24 +121,28 @@ private: #if DEBUG // debugging aid struct Debug { - void *last_return_address_alloc = nullptr; - void *last_return_address_dealloc = nullptr; - void *last_return_address_fill = nullptr; - void *last_return_address_subref = nullptr; + void *last_return_address_alloc; + void *last_return_address_dealloc; + void *last_return_address_fill; + void *last_return_address_subref; + Debug() { memset(this, 0, sizeof(*this)); } }; Debug debug; #endif - // disable copy, assignment and move assignment - MemBuffer(const MemBuffer &) = delete; - MemBuffer &operator=(const MemBuffer &) = delete; - MemBuffer &operator=(MemBuffer &&) = delete; + // disable copy, assignment and move + MemBuffer(const MemBuffer &) DELETED_FUNCTION; + MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION; +#if __cplusplus >= 201103L + MemBuffer(MemBuffer &&) DELETED_FUNCTION; + MemBuffer &operator=(MemBuffer &&) DELETED_FUNCTION; +#endif // disable dynamic allocation ACC_CXX_DISABLE_NEW_DELETE // 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] - MemBuffer *operator&() const = delete; + MemBuffer *operator&() const DELETED_FUNCTION; }; // raw_bytes overload @@ -148,14 +155,14 @@ template inline typename MemBufferBase::pointer raw_index_bytes(const MemBufferBase &mbb, size_t index, size_t size_in_bytes) { typedef typename MemBufferBase::element_type element_type; - return raw_bytes(mbb, mem_size(sizeof(element_type), index, size_in_bytes)) + index; + return mbb.raw_bytes(mem_size(sizeof(element_type), index, size_in_bytes)) + index; } // global operators // rewrite "n + membuffer" to "membuffer + n" so that this will get checked above -template ::value, U>::type> -inline typename MemBufferBase::pointer operator+(U n, const MemBufferBase &mbb) { +template +inline typename std::enable_if::value, typename MemBufferBase::pointer>::type +operator+(U n, const MemBufferBase &mbb) { return mbb + n; } diff --git a/src/util/util.cpp b/src/util/util.cpp index d471e514..fa4d444b 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -51,16 +51,16 @@ ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16 * 1024 * 1024 < upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2) { assert(element_size > 0); - if __acc_very_unlikely (element_size > UPX_RSIZE_MAX) + if very_unlikely (element_size > UPX_RSIZE_MAX) throwCantPack("mem_size 1; take care"); - if __acc_very_unlikely (n > UPX_RSIZE_MAX) + if very_unlikely (n > UPX_RSIZE_MAX) throwCantPack("mem_size 2; take care"); - if __acc_very_unlikely (extra1 > UPX_RSIZE_MAX) + if very_unlikely (extra1 > UPX_RSIZE_MAX) throwCantPack("mem_size 3; take care"); - if __acc_very_unlikely (extra2 > UPX_RSIZE_MAX) + if very_unlikely (extra2 > UPX_RSIZE_MAX) throwCantPack("mem_size 4; take care"); upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow - if __acc_very_unlikely (bytes > UPX_RSIZE_MAX) + if very_unlikely (bytes > UPX_RSIZE_MAX) throwCantPack("mem_size 5; take care"); return ACC_ICONV(upx_rsize_t, bytes); } @@ -68,16 +68,16 @@ upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t ext bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2) noexcept { assert(element_size > 0); - if __acc_very_unlikely (element_size > UPX_RSIZE_MAX) + if very_unlikely (element_size > UPX_RSIZE_MAX) return false; - if __acc_very_unlikely (n > UPX_RSIZE_MAX) + if very_unlikely (n > UPX_RSIZE_MAX) return false; - if __acc_very_unlikely (extra1 > UPX_RSIZE_MAX) + if very_unlikely (extra1 > UPX_RSIZE_MAX) return false; - if __acc_very_unlikely (extra2 > UPX_RSIZE_MAX) + if very_unlikely (extra2 > UPX_RSIZE_MAX) return false; upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow - if __acc_very_unlikely (bytes > UPX_RSIZE_MAX) + if very_unlikely (bytes > UPX_RSIZE_MAX) return false; return true; } @@ -98,18 +98,18 @@ TEST_CASE("mem_size") { } int ptr_diff_bytes(const void *a, const void *b) { - if __acc_very_unlikely (a == nullptr) { + if very_unlikely (a == nullptr) { throwCantPack("ptr_diff_bytes null 1; take care"); } - if __acc_very_unlikely (b == nullptr) { + if very_unlikely (b == nullptr) { throwCantPack("ptr_diff_bytes null 2; take care"); } ptrdiff_t d = (const char *) a - (const char *) b; if (a >= b) { - if __acc_very_unlikely (!mem_size_valid_bytes(d)) + if very_unlikely (!mem_size_valid_bytes(d)) throwCantPack("ptr_diff_bytes 1; take care"); } else { - if __acc_very_unlikely (!mem_size_valid_bytes(-d)) + if very_unlikely (!mem_size_valid_bytes(-d)) throwCantPack("ptr_diff_bytes 2; take care"); } return ACC_ICONV(int, d); @@ -117,7 +117,7 @@ int ptr_diff_bytes(const void *a, const void *b) { unsigned ptr_udiff_bytes(const void *a, const void *b) { int d = ptr_diff_bytes(a, b); - if __acc_very_unlikely (d < 0) + if very_unlikely (d < 0) throwCantPack("ptr_udiff_bytes; take care"); return ACC_ICONV(unsigned, d); } diff --git a/src/util/util.h b/src/util/util.h index 7fe14301..c3947272 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -40,20 +40,22 @@ 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 invalid size #define New(type, n) new type[mem_size_get_n(sizeof(type), n)] // will throw on invalid size upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2 = 0); +// // inline fast paths: +// // will throw on invalid size inline upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n) { upx_uint64_t bytes = element_size * n; - if __acc_very_unlikely (element_size == 0 || element_size > UPX_RSIZE_MAX || - n > UPX_RSIZE_MAX || bytes > UPX_RSIZE_MAX) + if very_unlikely (element_size == 0 || element_size > UPX_RSIZE_MAX || n > UPX_RSIZE_MAX || + bytes > UPX_RSIZE_MAX) return mem_size(element_size, n, 0, 0); // this will throw return ACC_ICONV(upx_rsize_t, bytes); } diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index b8264b76..1fad5aa1 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -33,37 +33,50 @@ XSPAN_NAMESPACE_BEGIN // debugging stats struct XSpanStats { upx_std_atomic(size_t) check_range_counter; + // doctest checks will set these: + upx_std_atomic(size_t) fail_nullptr; + upx_std_atomic(size_t) fail_nullbase; + upx_std_atomic(size_t) fail_not_same_base; + upx_std_atomic(size_t) fail_range_nullptr; + upx_std_atomic(size_t) fail_range_nullbase; + upx_std_atomic(size_t) fail_range_range; }; static XSpanStats xspan_stats; // HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience -__acc_noinline void xspan_fail_nullptr() { +noinline void xspan_fail_nullptr() { + xspan_stats.fail_nullptr += 1; throwCantUnpack("xspan unexpected NULL pointer; take care!"); } -__acc_noinline void xspan_fail_nullbase() { +noinline void xspan_fail_nullbase() { + xspan_stats.fail_nullbase += 1; throwCantUnpack("xspan unexpected NULL base; take care!"); } -__acc_noinline void xspan_fail_not_same_base() { +noinline void xspan_fail_not_same_base() { + xspan_stats.fail_not_same_base += 1; throwInternalError("xspan unexpected base pointer; take care!"); } -__acc_noinline void xspan_fail_range_nullptr() { +noinline void xspan_fail_range_nullptr() { + xspan_stats.fail_range_nullptr += 1; throwCantUnpack("xspan_check_range: unexpected NULL pointer; take care!"); } -__acc_noinline void xspan_fail_range_nullbase() { +noinline void xspan_fail_range_nullbase() { + xspan_stats.fail_range_nullbase += 1; throwCantUnpack("xspan_check_range: unexpected NULL base; take care!"); } -__acc_noinline void xspan_fail_range_range() { +noinline void xspan_fail_range_range() { + xspan_stats.fail_range_range += 1; throwCantUnpack("xspan_check_range: pointer out of range; take care!"); } void xspan_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes) { - if __acc_very_unlikely (p == nullptr) + if very_unlikely (p == nullptr) xspan_fail_range_nullptr(); - if __acc_very_unlikely (base == nullptr) + if very_unlikely (base == nullptr) xspan_fail_range_nullbase(); ptrdiff_t off = (const char *) p - (const char *) base; - if __acc_very_unlikely (off < 0 || off > size_in_bytes) + if very_unlikely (off < 0 || off > size_in_bytes) xspan_fail_range_range(); xspan_stats.check_range_counter += 1; // fprintf(stderr, "xspan_check_range done\n"); diff --git a/src/util/xspan.h b/src/util/xspan.h index 51a2318a..0cc89a08 100644 --- a/src/util/xspan.h +++ b/src/util/xspan.h @@ -159,4 +159,47 @@ inline R *xspan_make_helper__(R * /*dummy*/, MemBuffer &first) { #define SPAN_S_VAR XSPAN_S_VAR #endif +/************************************************************************* +// raw_bytes() - get underlying memory from checked buffers/pointers. +// This is overloaded by various utility classes like BoundedPtr, +// MemBuffer and XSpan. +// +// 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 +inline + typename std::enable_if::value && !std_is_bounded_array::value, T>::type + raw_bytes(T ptr, size_t size_in_bytes) { + if very_unlikely (size_in_bytes > 0 && ptr == nullptr) + throwInternalError("raw_bytes unexpected NULL ptr"); + return ptr; +} + +// default: for any regular pointer, raw_index_bytes() is just "pointer + index" +// NOTE: index == number of elements, *NOT* size in bytes! +template +inline + typename std::enable_if::value && !std_is_bounded_array::value, T>::type + raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) { + if very_unlikely (ptr == nullptr) + throwInternalError("raw_index_bytes unexpected NULL ptr"); + (void) mem_size(sizeof(T), index, size_in_bytes); // assert size + return ptr + index; +} + +// same for bounded arrays +template +inline T *raw_bytes(T (&a)[N], size_t size_in_bytes) { + if very_unlikely (size_in_bytes > mem_size(sizeof(T), N)) + throwInternalError("raw_bytes out of range"); + return a; +} + +template +inline T *raw_index_bytes(T (&a)[N], size_t index, size_t size_in_bytes) { + return raw_bytes(a, mem_size(sizeof(T), index, size_in_bytes)) + index; +} + /* vim:set ts=4 sw=4 et: */ diff --git a/src/util/xspan_impl.h b/src/util/xspan_impl.h index 3872afe3..3acb4052 100644 --- a/src/util/xspan_impl.h +++ b/src/util/xspan_impl.h @@ -42,12 +42,12 @@ XSPAN_NAMESPACE_BEGIN // HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience -__acc_noinline void xspan_fail_nullptr(); -__acc_noinline void xspan_fail_nullbase(); -__acc_noinline void xspan_fail_not_same_base(); -__acc_noinline void xspan_fail_range_nullptr(); -__acc_noinline void xspan_fail_range_nullbase(); -__acc_noinline void xspan_fail_range_range(); +noinline void xspan_fail_nullptr(); +noinline void xspan_fail_nullbase(); +noinline void xspan_fail_not_same_base(); +noinline void xspan_fail_range_nullptr(); +noinline void xspan_fail_range_nullbase(); +noinline void xspan_fail_range_range(); void xspan_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes); // help constructor to distinguish between number of elements and bytes diff --git a/src/util/xspan_impl_common.h b/src/util/xspan_impl_common.h index dad5602e..abe2d6f5 100644 --- a/src/util/xspan_impl_common.h +++ b/src/util/xspan_impl_common.h @@ -53,7 +53,7 @@ size_type size_in_bytes; // debug - internal sanity check; also serves as pseudo-documentation #if DEBUG -__acc_noinline void assertInvariants() const { +noinline void assertInvariants() const { if __acc_cte (configRequirePtr) assert(ptr != nullptr); if __acc_cte (configRequireBase) @@ -62,32 +62,32 @@ __acc_noinline void assertInvariants() const { xspan_check_range(ptr, base, size_in_bytes); } #else -__acc_forceinline void assertInvariants() const {} +forceinline void assertInvariants() const {} #endif -static __acc_forceinline pointer makeNotNull(pointer p) { - if __acc_very_unlikely (p == nullptr) +static forceinline pointer makeNotNull(pointer p) { + if very_unlikely (p == nullptr) xspan_fail_nullptr(); return p; } // enforce config invariants at constructor time - static functions -static __acc_forceinline pointer makePtr(pointer p) { +static forceinline pointer makePtr(pointer p) { if __acc_cte (configRequirePtr && p == nullptr) xspan_fail_nullptr(); return p; } -static __acc_forceinline pointer makeBase(pointer b) { +static forceinline pointer makeBase(pointer b) { if __acc_cte (configRequireBase && b == nullptr) xspan_fail_nullbase(); return b; } // inverse logic for ensuring valid pointers from existing objets -__acc_forceinline pointer ensurePtr() const { +forceinline pointer ensurePtr() const { if __acc_cte (!configRequirePtr && ptr == nullptr) xspan_fail_nullptr(); return ptr; } -__acc_forceinline pointer ensureBase() const { +forceinline pointer ensureBase() const { if __acc_cte (!configRequireBase && base == nullptr) xspan_fail_nullbase(); return base; @@ -213,7 +213,7 @@ Self &assign(const Self &other) { } else { // magic 2: assert same base (but ignore size_in_bytes !) if __acc_cte (configRequireBase || other.base != nullptr) - if __acc_very_unlikely (base != other.base) + if very_unlikely (base != other.base) xspan_fail_not_same_base(); if __acc_cte ((configRequirePtr || other.ptr != nullptr) && (configRequireBase || base != nullptr)) diff --git a/src/util/xspan_impl_ptr.h b/src/util/xspan_impl_ptr.h index c18b56fe..51106be4 100644 --- a/src/util/xspan_impl_ptr.h +++ b/src/util/xspan_impl_ptr.h @@ -51,11 +51,11 @@ private: pointer ptr; // enforce config invariants at constructor time - static functions - static __acc_forceinline pointer makePtr(pointer p) { return p; } + static forceinline pointer makePtr(pointer p) { return p; } // inverse logic for ensuring valid pointers from existing objets - __acc_forceinline pointer ensurePtr() const { return ptr; } + forceinline pointer ensurePtr() const { return ptr; } // debug - __acc_forceinline void assertInvariants() const {} + forceinline void assertInvariants() const {} public: #if XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1 @@ -172,9 +172,9 @@ public: #endif private: - __acc_forceinline pointer check_deref(pointer p) const { return p; } - __acc_forceinline pointer check_deref(pointer p, ptrdiff_t n) const { return p + n; } - __acc_forceinline pointer check_add(pointer p, ptrdiff_t n) const { return p + n; } + forceinline pointer check_deref(pointer p) const { return p; } + forceinline pointer check_deref(pointer p, ptrdiff_t n) const { return p + n; } + forceinline pointer check_add(pointer p, ptrdiff_t n) const { return p + n; } public: // raw access pointer raw_ptr() const { return ptr; }