diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f51b1a16..c4765d45 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -36,15 +36,27 @@ RUN set -eux \ && apt-get -y install --no-install-recommends \ python3-full \ python3-pip \ + python3-cogapp \ git \ wget \ cmake \ - && rm -rf /var/lib/apt/lists/* \ - && if pip help install | grep -q '\-\-break-system-packages'; then \ - pip install --no-cache-dir --break-system-packages cogapp; \ - else \ - pip install --no-cache-dir cogapp; \ - fi + clang-format \ + clang-format-18 \ + lcov \ + && rm -rf /var/lib/apt/lists/* + +RUN set -eux; \ + VERSION="2.4.1"; \ + case "$(uname -m)" in \ + x86_64) ARCH="amd64"; SHA256="bdaa2c0fbee03e5c2f99e605d9419386ce5d558440baac2017398faada839e04" ;; \ + aarch64) ARCH="arm64"; SHA256="0a09e1f04a0f8a86fd4e709552613f5d82adf6bc72f0a4b5e217670894e79fbf" ;; \ + *) echo "Unsupported architecture: $(uname -m)"; exit 1 ;; \ + esac; \ + wget -O treefmt.tar.gz "https://github.com/numtide/treefmt/releases/download/v${VERSION}/treefmt_${VERSION}_linux_${ARCH}.tar.gz" \ + && echo "${SHA256} treefmt.tar.gz" | sha256sum -c \ + && tar xzf treefmt.tar.gz treefmt \ + && install -m 755 treefmt /usr/bin/treefmt \ + && rm treefmt.tar.gz treefmt RUN set -eux \ && echo "Pip version: " \ diff --git a/.devcontainer/armhf/Dockerfile b/.devcontainer/armhf/Dockerfile new file mode 100644 index 00000000..7d555f36 --- /dev/null +++ b/.devcontainer/armhf/Dockerfile @@ -0,0 +1,54 @@ +# armhf Test Environment for ETL +# Uses QEMU user-mode emulation to run armhf binaries on x64 host +FROM debian:trixie + +# Avoid prompts from apt +ENV DEBIAN_FRONTEND=noninteractive + +# Install QEMU user-mode emulation and armhf cross-compilation tools +RUN dpkg --add-architecture armhf && \ + apt-get update && apt-get install -y --no-install-recommends \ + qemu-user-static \ + qemu-user \ + binfmt-support \ + gcc-arm-linux-gnueabihf \ + g++-arm-linux-gnueabihf \ + cmake \ + make \ + ninja-build \ + git \ + wget \ + file \ + libc6:armhf \ + libstdc++6:armhf \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user with stable UID/GID +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME} + +# Set working directory +WORKDIR /workspaces/etl + +# Verify QEMU and cross-compilation setup +RUN echo "=== Host Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== armhf Cross Compiler ===" && \ + arm-linux-gnueabihf-gcc --version && \ + echo "" && \ + echo "=== QEMU arm ===" && \ + qemu-arm-static --version | head -n1 + +# Ensure workspace directory ownership for non-root user +RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces + +# Switch to non-root user +USER ${USERNAME} + +# Default command +CMD ["/bin/bash"] diff --git a/.devcontainer/armhf/devcontainer.json b/.devcontainer/armhf/devcontainer.json new file mode 100644 index 00000000..a1dc285e --- /dev/null +++ b/.devcontainer/armhf/devcontainer.json @@ -0,0 +1,29 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "armhf (Debian)", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ], + "settings": { + "cmake.sourceDirectory": "${workspaceFolder}/test", + "cmake.configureArgs": [ + "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/armhf/toolchain-armhf.cmake", + "-DBUILD_TESTS=ON", + "-DNO_STL=OFF", + "-DETL_CXX_STANDARD=23" + ], + "cmake.buildDirectory": "${workspaceFolder}/build-armhf", + "cmake.generator": "Ninja" + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/armhf/toolchain-armhf.cmake b/.devcontainer/armhf/toolchain-armhf.cmake new file mode 100644 index 00000000..a7f9f00a --- /dev/null +++ b/.devcontainer/armhf/toolchain-armhf.cmake @@ -0,0 +1,21 @@ +# CMake toolchain file for armhf cross-compilation +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) + +# Specify the cross compiler +set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) +set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) +set(CMAKE_AR arm-linux-gnueabihf-ar) +set(CMAKE_RANLIB arm-linux-gnueabihf-ranlib) +set(CMAKE_STRIP arm-linux-gnueabihf-strip) + +# Search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# For libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set QEMU for running tests +set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-arm-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries") diff --git a/.devcontainer/i386/Dockerfile b/.devcontainer/i386/Dockerfile new file mode 100644 index 00000000..bace68cd --- /dev/null +++ b/.devcontainer/i386/Dockerfile @@ -0,0 +1,54 @@ +# i386 Test Environment for ETL +# Uses QEMU user-mode emulation to run i386 binaries on x64 host +FROM debian:trixie + +# Avoid prompts from apt +ENV DEBIAN_FRONTEND=noninteractive + +# Install QEMU user-mode emulation and i386 cross-compilation tools +RUN dpkg --add-architecture i386 && \ + apt-get update && apt-get install -y --no-install-recommends \ + qemu-user-static \ + qemu-user \ + binfmt-support \ + gcc-i686-linux-gnu \ + g++-i686-linux-gnu \ + cmake \ + make \ + ninja-build \ + git \ + wget \ + file \ + libc6:i386 \ + libstdc++6:i386 \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user with stable UID/GID +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME} + +# Set working directory +WORKDIR /workspaces/etl + +# Verify QEMU and cross-compilation setup +RUN echo "=== Host Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== i386 Cross Compiler ===" && \ + i686-linux-gnu-gcc --version && \ + echo "" && \ + echo "=== QEMU i386 ===" && \ + qemu-i386-static --version | head -n1 + +# Ensure workspace directory ownership for non-root user +RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces + +# Switch to non-root user +USER ${USERNAME} + +# Default command +CMD ["/bin/bash"] diff --git a/.devcontainer/i386/devcontainer.json b/.devcontainer/i386/devcontainer.json new file mode 100644 index 00000000..84e28a8e --- /dev/null +++ b/.devcontainer/i386/devcontainer.json @@ -0,0 +1,29 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "i386 (Debian)", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ], + "settings": { + "cmake.sourceDirectory": "${workspaceFolder}/test", + "cmake.configureArgs": [ + "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/i386/toolchain-i386.cmake", + "-DBUILD_TESTS=ON", + "-DNO_STL=OFF", + "-DETL_CXX_STANDARD=23" + ], + "cmake.buildDirectory": "${workspaceFolder}/build-i386", + "cmake.generator": "Ninja" + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/i386/toolchain-i386.cmake b/.devcontainer/i386/toolchain-i386.cmake new file mode 100644 index 00000000..502e2285 --- /dev/null +++ b/.devcontainer/i386/toolchain-i386.cmake @@ -0,0 +1,21 @@ +# CMake toolchain file for i386 cross-compilation +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR i386) + +# Specify the cross compiler +set(CMAKE_C_COMPILER i686-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER i686-linux-gnu-g++) +set(CMAKE_AR i686-linux-gnu-ar) +set(CMAKE_RANLIB i686-linux-gnu-ranlib) +set(CMAKE_STRIP i686-linux-gnu-strip) + +# Search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# For libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set QEMU for running tests +set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-i386-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries") diff --git a/.devcontainer/powerpc/Dockerfile b/.devcontainer/powerpc/Dockerfile new file mode 100644 index 00000000..faa94096 --- /dev/null +++ b/.devcontainer/powerpc/Dockerfile @@ -0,0 +1,79 @@ +# powerpc Test Environment for ETL +# Uses QEMU user-mode emulation to run powerpc binaries on x64 host +FROM debian:sid-20260406 + +# Avoid prompts from apt +ENV DEBIAN_FRONTEND=noninteractive + +# Install QEMU user-mode emulation and powerpc cross-compilation tools +RUN dpkg --add-architecture powerpc && \ + apt-get update && apt-get install -y --no-install-recommends \ + binfmt-support \ + gpg \ + ca-certificates \ + cmake \ + make \ + ninja-build \ + git \ + wget \ + file \ + debian-ports-archive-keyring \ + && rm -rf /var/lib/apt/lists/* + +RUN cat < /etc/apt/sources.list.d/debian.sources +Types: deb +URIs: http://snapshot.debian.org/archive/debian/20260406T000000Z +Suites: sid +Components: main +Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp +EOF + +RUN cat < /etc/apt/sources.list.d/powerpc.sources +Types: deb +URIs: http://snapshot.debian.org/archive/debian-ports/20260406T000000Z +Suites: sid +Components: main +Architectures: powerpc +Signed-By: /usr/share/keyrings/debian-ports-archive-keyring.gpg +EOF + +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid + +RUN apt-get update && apt-get install -y --no-install-recommends \ + qemu-user-static \ + qemu-user \ + gcc-powerpc-linux-gnu \ + g++-powerpc-linux-gnu \ + libc6:powerpc \ + libstdc++6:powerpc \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user with stable UID/GID +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME} + +# Set working directory +WORKDIR /workspaces/etl + +# Verify QEMU and cross-compilation setup +RUN echo "=== Host Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== powerpc Cross Compiler ===" && \ + powerpc-linux-gnu-gcc --version && \ + echo "" && \ + echo "=== QEMU powerpc ===" && \ + qemu-ppc-static --version | head -n1 + +# Ensure workspace directory ownership for non-root user +RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces + +# Switch to non-root user +USER ${USERNAME} + +# Default command +CMD ["/bin/bash"] diff --git a/.devcontainer/powerpc/devcontainer.json b/.devcontainer/powerpc/devcontainer.json new file mode 100644 index 00000000..1d7a9a05 --- /dev/null +++ b/.devcontainer/powerpc/devcontainer.json @@ -0,0 +1,29 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "powerpc (Debian)", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ], + "settings": { + "cmake.sourceDirectory": "${workspaceFolder}/test", + "cmake.configureArgs": [ + "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/powerpc/toolchain-powerpc.cmake", + "-DBUILD_TESTS=ON", + "-DNO_STL=ON", + "-DETL_CXX_STANDARD=23" + ], + "cmake.buildDirectory": "${workspaceFolder}/build-powerpc", + "cmake.generator": "Ninja" + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/powerpc/toolchain-powerpc.cmake b/.devcontainer/powerpc/toolchain-powerpc.cmake new file mode 100644 index 00000000..1afea7da --- /dev/null +++ b/.devcontainer/powerpc/toolchain-powerpc.cmake @@ -0,0 +1,21 @@ +# CMake toolchain file for powerpc cross-compilation +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR powerpc) + +# Specify the cross compiler +set(CMAKE_C_COMPILER powerpc-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER powerpc-linux-gnu-g++) +set(CMAKE_AR powerpc-linux-gnu-ar) +set(CMAKE_RANLIB powerpc-linux-gnu-ranlib) +set(CMAKE_STRIP powerpc-linux-gnu-strip) + +# Search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# For libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set QEMU for running tests +set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-ppc CACHE FILEPATH "Path to the emulator for cross-compiled binaries") diff --git a/.devcontainer/riscv64/Dockerfile b/.devcontainer/riscv64/Dockerfile new file mode 100644 index 00000000..7d07cdda --- /dev/null +++ b/.devcontainer/riscv64/Dockerfile @@ -0,0 +1,54 @@ +# riscv64 Test Environment for ETL +# Uses QEMU user-mode emulation to run riscv64 binaries on x64 host +FROM debian:trixie + +# Avoid prompts from apt +ENV DEBIAN_FRONTEND=noninteractive + +# Install QEMU user-mode emulation and riscv64 cross-compilation tools +RUN dpkg --add-architecture riscv64 && \ + apt-get update && apt-get install -y --no-install-recommends \ + qemu-user-static \ + qemu-user \ + binfmt-support \ + gcc-riscv64-linux-gnu \ + g++-riscv64-linux-gnu \ + cmake \ + make \ + ninja-build \ + git \ + wget \ + file \ + libc6:riscv64 \ + libstdc++6:riscv64 \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user with stable UID/GID +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME} + +# Set working directory +WORKDIR /workspaces/etl + +# Verify QEMU and cross-compilation setup +RUN echo "=== Host Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== riscv64 Cross Compiler ===" && \ + riscv64-linux-gnu-gcc --version && \ + echo "" && \ + echo "=== QEMU riscv64 ===" && \ + qemu-riscv64-static --version | head -n1 + +# Ensure workspace directory ownership for non-root user +RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces + +# Switch to non-root user +USER ${USERNAME} + +# Default command +CMD ["/bin/bash"] diff --git a/.devcontainer/riscv64/devcontainer.json b/.devcontainer/riscv64/devcontainer.json new file mode 100644 index 00000000..0e673f24 --- /dev/null +++ b/.devcontainer/riscv64/devcontainer.json @@ -0,0 +1,29 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/cpp +{ + "name": "riscv64 (Debian)", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ], + "settings": { + "cmake.sourceDirectory": "${workspaceFolder}/test", + "cmake.configureArgs": [ + "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/riscv64/toolchain-riscv64.cmake", + "-DBUILD_TESTS=ON", + "-DNO_STL=OFF", + "-DETL_CXX_STANDARD=23" + ], + "cmake.buildDirectory": "${workspaceFolder}/build-riscv64", + "cmake.generator": "Ninja" + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/riscv64/toolchain-riscv64.cmake b/.devcontainer/riscv64/toolchain-riscv64.cmake new file mode 100644 index 00000000..adc1c7f3 --- /dev/null +++ b/.devcontainer/riscv64/toolchain-riscv64.cmake @@ -0,0 +1,20 @@ +# CMake toolchain file for riscv64 cross-compilation +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR riscv64) + +# Specify the cross compiler +set(CMAKE_C_COMPILER riscv64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER riscv64-linux-gnu-g++) +set(CMAKE_AR riscv64-linux-gnu-ar) +set(CMAKE_RANLIB riscv64-linux-gnu-ranlib) +set(CMAKE_STRIP riscv64-linux-gnu-strip) +# Search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# For libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set QEMU for running tests +set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-riscv64-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries") diff --git a/.devcontainer/run-tests.sh b/.devcontainer/run-tests.sh new file mode 100755 index 00000000..218dc032 --- /dev/null +++ b/.devcontainer/run-tests.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Run tests inside the separately created docker container for different hardware architecture +# +# Strategy: +# * Create docker image +# * Enter image +# * Cross build tests +# * Run tests via QEMU +# + +set -e + +usage() +{ + echo "Usage: run-tests.sh " + echo "Architecture: armhf|i386|powerpc|riscv64|s390x" + echo "(run from project root)" +} + +ARCHLIST="armhf i386 powerpc riscv64 s390x" + +if [[ " $ARCHLIST " =~ " $1 " ]] ; then + ARCH=$1 +else + echo "Unsupported architecture: $1" + usage + exit 1 +fi + +if [ "$2" = "" ] ; then + echo "Creating docker image..." + docker build -t $ARCH .devcontainer/$ARCH + + echo "Entering container..." + docker run -it --rm -v "$PWD":/workspaces/etl -w /workspaces/etl $ARCH /bin/bash .devcontainer/run-tests.sh $ARCH inside_container + +elif [ "$2" = "inside_container" ] ; then + echo "Cross building tests..." + mkdir -p build-$ARCH + cd build-$ARCH + cmake -DCMAKE_TOOLCHAIN_FILE=../.devcontainer/$ARCH/toolchain-$ARCH.cmake \ + -DBUILD_TESTS=ON -DNO_STL=ON -DETL_CXX_STANDARD=23 \ + -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=-O0 -DETL_ENABLE_SANITIZER=Off -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \ + ../test + export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) + cmake --build . + + echo "Running tests via CTest (using QEMU emulator from toolchain)..." + ctest -V --output-on-failure + echo "Tests successful." +else + echo "Invalid second argument: $2" + usage + exit 1 +fi diff --git a/.devcontainer/s390x/Dockerfile b/.devcontainer/s390x/Dockerfile index 21a6289c..5656bc1d 100644 --- a/.devcontainer/s390x/Dockerfile +++ b/.devcontainer/s390x/Dockerfile @@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive # Install QEMU user-mode emulation and s390x cross-compilation tools RUN dpkg --add-architecture s390x && \ - apt-get update && apt-get install -y --no-install-recommends\ + apt-get update && apt-get install -y --no-install-recommends \ qemu-user-static \ qemu-user \ binfmt-support \ @@ -23,6 +23,14 @@ RUN dpkg --add-architecture s390x && \ libstdc++6:s390x \ && rm -rf /var/lib/apt/lists/* +# Create non-root user with stable UID/GID +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME} + # Set working directory WORKDIR /workspaces/etl @@ -36,5 +44,11 @@ RUN echo "=== Host Architecture ===" && \ echo "=== QEMU s390x ===" && \ qemu-s390x-static --version | head -n1 +# Ensure workspace directory ownership for non-root user +RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces + +# Switch to non-root user +USER ${USERNAME} + # Default command CMD ["/bin/bash"] diff --git a/.devcontainer/s390x/devcontainer.json b/.devcontainer/s390x/devcontainer.json index 8b7f8235..535a0799 100644 --- a/.devcontainer/s390x/devcontainer.json +++ b/.devcontainer/s390x/devcontainer.json @@ -18,7 +18,7 @@ "-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/s390x/toolchain-s390x.cmake", "-DBUILD_TESTS=ON", "-DNO_STL=OFF", - "-DETL_CXX_STANDARD=17" + "-DETL_CXX_STANDARD=23" ], "cmake.buildDirectory": "${workspaceFolder}/build-s390x", "cmake.generator": "Ninja" diff --git a/.github/workflows/clang-c++11.yml b/.github/workflows/clang-c++11.yml index d511f5b7..6b73b7c1 100644 --- a/.github/workflows/clang-c++11.yml +++ b/.github/workflows/clang-c++11.yml @@ -25,7 +25,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/clang-c++14.yml b/.github/workflows/clang-c++14.yml index d06778b1..830832b5 100644 --- a/.github/workflows/clang-c++14.yml +++ b/.github/workflows/clang-c++14.yml @@ -25,7 +25,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/clang-c++17.yml b/.github/workflows/clang-c++17.yml index 9fb4611f..6ae2f4b9 100644 --- a/.github/workflows/clang-c++17.yml +++ b/.github/workflows/clang-c++17.yml @@ -25,7 +25,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/clang-c++20.yml b/.github/workflows/clang-c++20.yml index c68f9870..e246a795 100644 --- a/.github/workflows/clang-c++20.yml +++ b/.github/workflows/clang-c++20.yml @@ -32,7 +32,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -61,7 +61,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -90,7 +90,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -112,7 +112,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -134,7 +134,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -156,7 +156,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -178,7 +178,7 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v diff --git a/.github/workflows/clang-c++23.yml b/.github/workflows/clang-c++23.yml index ffa88744..acd22a41 100644 --- a/.github/workflows/clang-c++23.yml +++ b/.github/workflows/clang-c++23.yml @@ -30,9 +30,9 @@ jobs: export CC=clang-17 export CXX=clang++-17 export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -59,9 +59,9 @@ jobs: export CC=clang-17 export CXX=clang++-17 export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -88,9 +88,9 @@ jobs: export CC=clang-17 export CXX=clang++-17 export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ clang-17 --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -110,9 +110,9 @@ jobs: export CC=clang export CXX=clang++ export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -132,9 +132,9 @@ jobs: export CC=clang export CXX=clang++ export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -154,9 +154,9 @@ jobs: export CC=clang export CXX=clang++ export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -176,9 +176,9 @@ jobs: export CC=clang export CXX=clang++ export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 - cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v diff --git a/.github/workflows/clang-c++26.yml b/.github/workflows/clang-c++26.yml new file mode 100644 index 00000000..5a2e9be0 --- /dev/null +++ b/.github/workflows/clang-c++26.yml @@ -0,0 +1,189 @@ +name: clang-c++26 +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-clang-cpp26-linux-stl: + name: Clang C++26 Linux - STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-linux-no-stl: + name: Clang C++26 Linux - No STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-linux-stl-force-cpp03: + name: Clang C++26 Linux - STL - Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-linux-no-stl-force-cpp03: + name: Clang C++26 Linux - No STL - Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-osx-stl: + name: Clang C++26 OSX - STL + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-26] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-osx-no-stl: + name: Clang C++26 OSX - No STL + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-26] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-osx-stl-force-cpp03: + name: Clang C++26 OSX - STL - Force C++03 + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-26] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-clang-cpp26-osx-no-stl-force-cpp03: + name: Clang C++26 OSX - No STL - Force C++03 + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-26] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + clang --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v diff --git a/.github/workflows/clang-syntax-checks.yml b/.github/workflows/clang-syntax-checks.yml index 700b2087..416ef290 100644 --- a/.github/workflows/clang-syntax-checks.yml +++ b/.github/workflows/clang-syntax-checks.yml @@ -23,10 +23,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp03-linux-No-STL: - name: Syntax Check - Clang C++03 Linux No STL + name: Syntax Check - Clang C++03 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -41,7 +41,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp11-linux-STL: name: Syntax Check - Clang C++11 Linux STL @@ -59,10 +59,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp11-linux-No-STL: - name: Syntax Check - Clang C++11 Linux No STL + name: Syntax Check - Clang C++11 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -77,7 +77,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp11-linux-STL-Force-CPP03: name: Syntax Check - Clang C++11 Linux STL Force C++03 @@ -95,7 +95,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp11-linux-No-STL-Force-CPP03: name: Syntax Check - Clang C++11 Linux No STL Force C++03 @@ -113,7 +113,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp14-linux-STL: name: Syntax Check - Clang C++14 Linux STL @@ -131,10 +131,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp14-linux-No-STL: - name: Syntax Check - Clang C++14 Linux No STL + name: Syntax Check - Clang C++14 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -149,7 +149,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp14-linux-STL-Force-CPP03: name: Syntax Check - Clang C++14 Linux STL Force C++03 @@ -167,7 +167,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp14-linux-No-STL-Force-CPP03: name: Syntax Check - Clang C++14 Linux No STL Force C++03 @@ -185,7 +185,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp17-linux-STL: name: Syntax Check - Clang C++17 Linux STL @@ -203,10 +203,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp17-linux-No-STL: - name: Syntax Check - Clang C++17 Linux No STL + name: Syntax Check - Clang C++17 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -221,7 +221,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp17-linux-STL-Force-CPP03: name: Syntax Check - Clang C++17 Linux STL Force C++03 @@ -239,7 +239,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp17-linux-No-STL-Force-CPP03: name: Syntax Check - Clang C++17 Linux No STL Force C++03 @@ -257,7 +257,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp20-linux-STL: name: Syntax Check - Clang C++20 Linux STL @@ -275,10 +275,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp20-linux-No-STL: - name: Syntax Check - Clang C++20 Linux No STL + name: Syntax Check - Clang C++20 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -293,7 +293,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp20-linux-STL-Force-CPP03: name: Syntax Check - Clang C++20 Linux STL Force C++03 @@ -311,7 +311,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp20-linux-No-STL-Force-CPP03: name: Syntax Check - Clang C++20 Linux No STL Force C++03 @@ -329,7 +329,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp23-linux-STL: name: Syntax Check - Clang C++23 Linux STL @@ -347,10 +347,10 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp23-linux-No-STL: - name: Syntax Check - Clang C++23 Linux No STL + name: Syntax Check - Clang C++23 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -365,7 +365,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp23-linux-STL-Force-CPP03: name: Syntax Check - Clang C++23 Linux STL Force C++03 @@ -383,7 +383,7 @@ jobs: export CXX=clang++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-clang-cpp23-linux-No-STL-Force-CPP03: name: Syntax Check - Clang C++23 Linux No STL Force C++03 @@ -401,4 +401,80 @@ jobs: export CXX=clang++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check clang --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-clang-cpp26-linux-STL: + name: Syntax Check - Clang C++26 Linux STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check + clang++ --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-clang-cpp26-linux-No-STL: + name: Syntax Check - Clang C++26 Linux No STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check + clang++ --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-clang-cpp26-linux-STL-Force-CPP03: + name: Syntax Check - Clang C++26 Linux STL Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check + clang++ --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-clang-cpp26-linux-No-STL-Force-CPP03: + name: Syntax Check - Clang C++26 Linux No STL Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=clang + export CXX=clang++ + cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check + clang++ --version + make -j "$(getconf _NPROCESSORS_ONLN)" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 79f9553e..5c05ebef 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -65,8 +65,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 - -# GitHub Repository settings -# -> Settings -> Pages -# -> Source: gh actions + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/gcc-c++11.yml b/.github/workflows/gcc-c++11.yml index 571c6d6e..c9706aeb 100644 --- a/.github/workflows/gcc-c++11.yml +++ b/.github/workflows/gcc-c++11.yml @@ -26,7 +26,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -49,7 +49,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v diff --git a/.github/workflows/gcc-c++14.yml b/.github/workflows/gcc-c++14.yml index f623af08..a3277b66 100644 --- a/.github/workflows/gcc-c++14.yml +++ b/.github/workflows/gcc-c++14.yml @@ -25,7 +25,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/gcc-c++17.yml b/.github/workflows/gcc-c++17.yml index fc0ddd97..dbeef7fa 100644 --- a/.github/workflows/gcc-c++17.yml +++ b/.github/workflows/gcc-c++17.yml @@ -25,7 +25,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v diff --git a/.github/workflows/gcc-c++20.yml b/.github/workflows/gcc-c++20.yml index 5965e05e..be4e6fb2 100644 --- a/.github/workflows/gcc-c++20.yml +++ b/.github/workflows/gcc-c++20.yml @@ -25,7 +25,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -47,7 +47,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -69,7 +69,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -91,7 +91,7 @@ jobs: export CXX=g++ cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/gcc-c++23-armhf.yml b/.github/workflows/gcc-c++23-armhf.yml new file mode 100644 index 00000000..1bd2912b --- /dev/null +++ b/.github/workflows/gcc-c++23-armhf.yml @@ -0,0 +1,29 @@ +name: gcc-c++23-armhf +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp23-linux-no-stl-armhf: + name: GCC C++23 Linux - No STL - armhf + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t etl-armhf -f .devcontainer/armhf/Dockerfile . + + - name: Build and run tests + run: | + docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-armhf bash -c "\ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \ + -DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/armhf/toolchain-armhf.cmake \ + -DEXTRA_TESTING_FLAGS=-v \ + ./ && \ + cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \ + ctest -V" diff --git a/.github/workflows/gcc-c++23-i386.yml b/.github/workflows/gcc-c++23-i386.yml new file mode 100644 index 00000000..31bfc331 --- /dev/null +++ b/.github/workflows/gcc-c++23-i386.yml @@ -0,0 +1,29 @@ +name: gcc-c++23-i386 +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp23-linux-no-stl-i386: + name: GCC C++23 Linux - No STL - i386 + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t etl-i386 -f .devcontainer/i386/Dockerfile . + + - name: Build and run tests + run: | + docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-i386 bash -c "\ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \ + -DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/i386/toolchain-i386.cmake \ + -DEXTRA_TESTING_FLAGS=-v \ + ./ && \ + cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \ + ctest -V" diff --git a/.github/workflows/gcc-c++23-powerpc.yml b/.github/workflows/gcc-c++23-powerpc.yml new file mode 100644 index 00000000..7494ae55 --- /dev/null +++ b/.github/workflows/gcc-c++23-powerpc.yml @@ -0,0 +1,29 @@ +name: gcc-c++23-powerpc +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp23-linux-no-stl-powerpc: + name: GCC C++23 Linux - No STL - powerpc + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t etl-powerpc -f .devcontainer/powerpc/Dockerfile . + + - name: Build and run tests + run: | + docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-powerpc bash -c "\ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \ + -DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/powerpc/toolchain-powerpc.cmake \ + -DEXTRA_TESTING_FLAGS=-v \ + ./ && \ + cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \ + ctest -V" diff --git a/.github/workflows/gcc-c++23-riscv64.yml b/.github/workflows/gcc-c++23-riscv64.yml new file mode 100644 index 00000000..695056a8 --- /dev/null +++ b/.github/workflows/gcc-c++23-riscv64.yml @@ -0,0 +1,29 @@ +name: gcc-c++23-riscv64 +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp23-linux-no-stl-riscv64: + name: GCC C++23 Linux - No STL - riscv64 + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t etl-riscv64 -f .devcontainer/riscv64/Dockerfile . + + - name: Build and run tests + run: | + docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-riscv64 bash -c "\ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \ + -DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/riscv64/toolchain-riscv64.cmake \ + -DEXTRA_TESTING_FLAGS=-v \ + ./ && \ + cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \ + ctest -V" diff --git a/.github/workflows/gcc-c++23-s390x.yml b/.github/workflows/gcc-c++23-s390x.yml new file mode 100644 index 00000000..f6a15aca --- /dev/null +++ b/.github/workflows/gcc-c++23-s390x.yml @@ -0,0 +1,29 @@ +name: gcc-c++23-s390x +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp23-linux-no-stl-s390x: + name: GCC C++23 Linux - No STL - s390x + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t etl-s390x -f .devcontainer/s390x/Dockerfile . + + - name: Build and run tests + run: | + docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-s390x bash -c "\ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \ + -DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \ + -DEXTRA_TESTING_FLAGS=-v \ + ./ && \ + cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \ + ctest -V" diff --git a/.github/workflows/gcc-c++23.yml b/.github/workflows/gcc-c++23.yml index f91924bd..654deff9 100644 --- a/.github/workflows/gcc-c++23.yml +++ b/.github/workflows/gcc-c++23.yml @@ -23,9 +23,9 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 export CC=gcc export CXX=g++ - cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./ + cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -45,9 +45,9 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 export CC=gcc export CXX=g++ - cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -67,9 +67,9 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 export CC=gcc export CXX=g++ - cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v @@ -89,9 +89,9 @@ jobs: export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 export CC=gcc export CXX=g++ - cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./ gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" - name: Run tests run: ./test/etl_tests -v \ No newline at end of file diff --git a/.github/workflows/gcc-c++26.yml b/.github/workflows/gcc-c++26.yml new file mode 100644 index 00000000..8f3701b0 --- /dev/null +++ b/.github/workflows/gcc-c++26.yml @@ -0,0 +1,101 @@ +name: gcc-c++26 +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + + build-gcc-cpp26-linux-stl: + name: GCC C++26 Linux - STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + export CC=gcc + export CXX=g++ + cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-gcc-cpp26-linux-no-stl: + name: GCC C++26 Linux - No STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + export CC=gcc + export CXX=g++ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./ + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-gcc-cpp26-linux-stl-force-cpp03: + name: GCC C++26 Linux - STL - Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + export CC=gcc + export CXX=g++ + cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v + + build-gcc-cpp26-linux-no-stl-force-cpp03: + name: GCC C++26 Linux - No STL - Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0 + export CC=gcc + export CXX=g++ + cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./ + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + - name: Run tests + run: ./test/etl_tests -v diff --git a/.github/workflows/gcc-syntax-checks.yml b/.github/workflows/gcc-syntax-checks.yml index 5f3753b1..81bfa4c4 100644 --- a/.github/workflows/gcc-syntax-checks.yml +++ b/.github/workflows/gcc-syntax-checks.yml @@ -23,10 +23,10 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp03-linux-No-STL: - name: Syntax Check - GCC C++03 Linux No STL + name: Syntax Check - GCC C++03 Linux No STL runs-on: ${{ matrix.os }} strategy: matrix: @@ -41,7 +41,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=03 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp11-linux-STL: name: Syntax Check - GCC C++11 Linux STL @@ -59,7 +59,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp11-linux-No-STL: name: Syntax Check - GCC C++11 Linux No STL @@ -77,7 +77,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=11 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp11-linux-STL-Force-CPP03: name: Syntax Check - GCC C++11 Linux STL Force C++03 @@ -95,7 +95,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp11-linux-No-STL-Force-CPP03: name: Syntax Check - GCC C++11 Linux No STL Force C++03 @@ -113,7 +113,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=11 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp14-linux-STL: name: Syntax Check - GCC C++14 Linux STL @@ -131,7 +131,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp14-linux-No-STL: name: Syntax Check - GCC C++14 Linux No STL @@ -149,7 +149,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=14 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp14-linux-STL-Force-CPP03: name: Syntax Check - GCC C++14 Linux STL Force C++03 @@ -167,7 +167,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp14-linux-No-STL-Force-CPP03: name: Syntax Check - GCC C++14 Linux No STL Force C++03 @@ -185,7 +185,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=14 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp17-linux-STL: name: Syntax Check - GCC C++17 Linux STL @@ -203,7 +203,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp17-linux-No-STL: name: Syntax Check - GCC C++17 Linux No STL @@ -221,7 +221,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp17-linux-STL-Force-CPP03: name: Syntax Check - GCC C++17 Linux STL Force C++03 @@ -239,7 +239,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp17-linux-No-STL-Force-CPP03: name: Syntax Check - GCC C++17 Linux No STL Force C++03 @@ -257,7 +257,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp20-linux-STL: name: Syntax Check - GCC C++20 Linux STL @@ -275,7 +275,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp20-linux-No-STL: name: Syntax Check - GCC C++20 Linux No STL @@ -293,7 +293,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp20-linux-STL-Force-CPP03: name: Syntax Check - GCC C++20 Linux STL Force C++03 @@ -311,7 +311,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp20-linux-No-STL-Force-CPP03: name: Syntax Check - GCC C++20 Linux No STL Force C++03 @@ -329,7 +329,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=20 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp23-linux-STL: name: Syntax Check - GCC C++23 Linux STL @@ -347,7 +347,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp23-linux-No-STL: name: Syntax Check - GCC C++23 Linux No STL @@ -365,7 +365,7 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp23-linux-STL-Force-CPP03: name: Syntax Check - GCC C++23 Linux STL Force C++03 @@ -383,7 +383,7 @@ jobs: export CXX=g++ cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) + make -j "$(getconf _NPROCESSORS_ONLN)" build-gcc-cpp23-linux-No-STL-Force-CPP03: name: Syntax Check - GCC C++23 Linux No STL Force C++03 @@ -401,4 +401,80 @@ jobs: export CXX=g++ cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./test/syntax_check gcc --version - make -j $(getconf _NPROCESSORS_ONLN) \ No newline at end of file + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-gcc-cpp26-linux-STL: + name: Syntax Check - GCC C++26 Linux STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=gcc + export CXX=g++ + cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-gcc-cpp26-linux-No-STL: + name: Syntax Check - GCC C++26 Linux No STL + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=gcc + export CXX=g++ + cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=26 ./test/syntax_check + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-gcc-cpp26-linux-STL-Force-CPP03: + name: Syntax Check - GCC C++26 Linux STL Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=gcc + export CXX=g++ + cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" + + build-gcc-cpp26-linux-No-STL-Force-CPP03: + name: Syntax Check - GCC C++26 Linux No STL Force C++03 + if: false # enabled when ubuntu-26.04 is available in github + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-26.04] + + steps: + - uses: actions/checkout@v4 + + - name: Build + run: | + export CC=gcc + export CXX=g++ + cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=26 ./test/syntax_check + gcc --version + make -j "$(getconf _NPROCESSORS_ONLN)" diff --git a/.github/workflows/generator.yml b/.github/workflows/generator.yml index 032ffd1e..1829c342 100644 --- a/.github/workflows/generator.yml +++ b/.github/workflows/generator.yml @@ -14,12 +14,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Generate + - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y python3-cogapp - cd include/etl/generators && bash generate.bat - - name: Check Generated Headers For Changes + - name: Run generator_test.py run: | - git diff --exit-code + cd scripts && python3 generator_test.py diff --git a/README.md b/README.md index 869455a0..1af9c518 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![GitHub release (latest by date)](https://img.shields.io/github/v/release/jwellbelove/etl) [![Release date](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3) -[![Standard](https://img.shields.io/badge/c%2B%2B-98/03/11/14/17/20/23-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) +[![Standard](https://img.shields.io/badge/c%2B%2B-98/03/11/14/17/20/23/26-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) ![GitHub contributors](https://img.shields.io/github/contributors-anon/ETLCPP/etl) ![GitHub forks](https://img.shields.io/github/forks/ETLCPP/etl?style=flat) @@ -15,6 +15,7 @@ ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++17.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++20.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++23.yml/badge.svg?branch=master) +![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++26.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-syntax-checks.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++11.yml/badge.svg?branch=master) @@ -22,6 +23,7 @@ ![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++17.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++20.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++23.yml/badge.svg?branch=master) +![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-c++26.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/clang-syntax-checks.yml/badge.svg?branch=master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3c14cd918ccf40008d0bcd7b083d5946)](https://www.codacy.com/manual/jwellbelove/etl?utm_source=github.com&utm_medium=referral&utm_content=ETLCPP/etl&utm_campaign=Badge_Grade) @@ -49,7 +51,7 @@ Its design goals include: - Offering APIs that closely resemble those of the STL, enabling familiar and consistent usage. - Maintaining compatibility with C++98 while implementing many features introduced in later standards -(C++11/14/17/20/23) where possible. +(C++11/14/17/20/23/26) where possible. - Ensuring deterministic behavior, which is critical in real-time and resource-constrained environments. diff --git a/docs/docker.md b/docs/docker.md new file mode 100644 index 00000000..2dc8d25d --- /dev/null +++ b/docs/docker.md @@ -0,0 +1,289 @@ +# Docker for Development + +## Overview + +The ETL repository ships a set of Docker-based development environments under +`.devcontainer/`. They give every contributor an identical, reproducible toolchain +regardless of host operating system. Three flavours are provided: + +| Flavour | Path | Purpose | +|---|---|---| +| **Default** | `.devcontainer/` | Day-to-day development (Microsoft C++ dev-container base image) | +| **Compiler-specific** | `.devcontainer/gcc09/` … `.devcontainer/gcc15/`, `.devcontainer/clang7/` … `.devcontainer/clang21/` | Test against a specific GCC or Clang version | +| **s390x big-endian** | `.devcontainer/s390x/` | Cross-compile and run tests on an s390x target via QEMU | + +All containers include CMake, Make, Git, Python 3, cogapp (the code generator used +by ETL), clang-format 18, and treefmt. + +## Prerequisites + +- **Docker** (or Docker Desktop) – any recent version that supports `docker build` + and `docker run`. +- **VS Code** with the + [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + extension (optional, but recommended for the smoothest experience). +- **Git** – to clone the repository. + +## Quick Start + +### Using the helper script + +The fastest way to get a shell inside the default container from the project root: + +```bash +./scripts/run-docker.sh +``` + +This script performs two steps: + +1. **Builds** the image from `.devcontainer/Dockerfile` and tags it `etl`. +2. **Runs** an interactive container that bind-mounts the repository at + `/home/vscode/etl` so that edits made inside the container are visible on + the host (and vice versa). + +You are dropped into a Bash shell as the `vscode` user with the working +directory set to the repository root. + +### Using VS Code Dev Containers + +1. Open the repository folder in VS Code. +2. When prompted, click **Reopen in Container** – or run the command + *Dev Containers: Reopen in Container* from the command palette. +3. VS Code reads `.devcontainer/devcontainer.json`, builds the image, and + attaches to the running container automatically. + +To open a **specific compiler variant** instead, run +*Dev Containers: Open Folder in Container…* and pick the sub-folder (e.g. +`.devcontainer/gcc14/`), or use the command palette action +*Dev Containers: Open Named Container Configuration…* and select the desired +name (e.g. "Gcc 14", "Clang 18"). + +## Default Development Container + +The file `.devcontainer/Dockerfile` is a multi-purpose image used by the +default configuration **and** by every compiler-specific variant (they simply +override the `BASE_IMAGE_NAME` build argument). + +### Base image + +```text +mcr.microsoft.com/devcontainers/cpp:2 +``` + +The exact digest is pinned in `devcontainer.json` so that builds are +reproducible even if the upstream tag is updated. + +### Installed tools + +The Dockerfile installs the following on top of the base image: + +| Tool | Purpose | +|---|---| +| `python3`, `pip` | Runtime for helper scripts | +| `python3-cogapp` / `cogapp` | ETL code generator | +| `git` | Version control | +| `wget` | Downloading additional tooling | +| `cmake`, `make` | Build system | +| `clang-format` (v18) | Source formatting (see [source-formatting.md](source-formatting.md)) | +| `treefmt` (v2.4.1) | Single-command formatting wrapper | + +### Reproducible builds with Debian snapshots + +The default configuration sets the build argument +`DEBIAN_SNAPSHOT=20260223T000000Z`. When this value is not `"none"`, the +Dockerfile rewrites the APT sources to point at +`snapshot.debian.org/archive/debian/`, ensuring that every +contributor installs identical package versions. Compiler-specific variants +that are based on upstream `gcc:*` or `silkeh/clang:*` images set +`DEBIAN_SNAPSHOT=none` because those images manage their own package sources. + +## Compiler-Specific Containers + +Each sub-folder under `.devcontainer/` contains a `devcontainer.json` that +reuses the **same** `Dockerfile` (`../Dockerfile`) but overrides the +`BASE_IMAGE_NAME` build argument to select a different compiler. + +### GCC variants + +| Folder | Base image | Name | +|---|---|---| +| `gcc09/` | `gcc:9` | Gcc 09 | +| `gcc10/` | `gcc:10` | Gcc 10 | +| `gcc11/` | `gcc:11` | Gcc 11 | +| `gcc12/` | `gcc:12` | Gcc 12 | +| `gcc13/` | `gcc:13` | Gcc 13 | +| `gcc14/` | `gcc:14` | Gcc 14 | +| `gcc15/` | `gcc:15` | Gcc 15 | + +### Clang variants + +| Folder | Base image | Name | +|---|---|---| +| `clang7/` | `silkeh/clang:7` | Clang 7 | +| `clang8/` | `silkeh/clang:8` | Clang 8 | +| `clang9/` | `silkeh/clang:9` | Clang 9 | +| `clang10/` | `silkeh/clang:10` | Clang 10 | +| `clang11/` | `silkeh/clang:11` | Clang 11 | +| `clang12/` | `silkeh/clang:12` | Clang 12 | +| `clang13/` | `silkeh/clang:13` | Clang 13 | +| `clang14/` | `silkeh/clang:14` | Clang 14 | +| `clang15/` | `silkeh/clang:15` | Clang 15 | +| `clang16/` | `silkeh/clang:16` | Clang 16 | +| `clang17/` | `silkeh/clang:17` | Clang 17 | +| `clang18/` | `silkeh/clang:18` | Clang 18 | +| `clang19/` | `silkeh/clang:19` | Clang 19 | +| `clang20/` | `silkeh/clang:20` | Clang 20 | +| `clang21/` | `silkeh/clang:21` | Clang 21 | + +All compiler-specific variants set `DEBIAN_SNAPSHOT` to `"none"` because they +rely on the upstream image's own package sources. + +## s390x Big-Endian Cross-Compilation + +The `s390x` container lives in `.devcontainer/s390x/` and has its **own** +Dockerfile (it does not reuse the default one). It is based on +`debian:trixie` and installs: + +- QEMU user-mode emulation (`qemu-user-static`, `qemu-user`, `binfmt-support`) +- s390x cross-compilation toolchain (`gcc-s390x-linux-gnu`, + `g++-s390x-linux-gnu`) +- CMake, Make, Ninja, Git, wget + +### Container setup + +Open `.devcontainer/s390x/` as a Dev Container in VS Code, or build manually: + +```bash +docker build -t etl-s390x .devcontainer/s390x +docker run -it --rm -v .:/workspaces/etl -w /workspaces/etl etl-s390x +``` + +### CMake toolchain + +A CMake toolchain file is provided at +`.devcontainer/s390x/toolchain-s390x.cmake`. It sets: + +- `CMAKE_SYSTEM_PROCESSOR` to `s390x` +- Cross-compilers `s390x-linux-gnu-gcc` / `g++` +- `CMAKE_CROSSCOMPILING_EMULATOR` to `/usr/bin/qemu-s390x-static` + +The VS Code Dev Container configuration already passes this toolchain file +via `cmake.configureArgs`, so CMake Tools picks it up automatically. + +### Running tests under QEMU + +Because the toolchain file sets `CMAKE_CROSSCOMPILING_EMULATOR`, CTest +automatically invokes `qemu-s390x-static` when running test binaries. +No extra flags are needed: + +```bash +cmake -S test -B build-s390x \ + -DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \ + -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_CXX_STANDARD=17 -G Ninja +cmake --build build-s390x +ctest --test-dir build-s390x +``` + +## Building and Running Tests + +Once inside any container (default, compiler-specific, or s390x) you can +build and run the ETL test suite. + +### Quick CMake workflow + +```bash +# Configure – build tests with C++17 +cmake -S test -B build -DBUILD_TESTS=ON -DETL_CXX_STANDARD=17 + +# Build +cmake --build build -j $(nproc) + +# Run tests +ctest --test-dir build +``` + +Change `DETL_CXX_STANDARD` to `11`, `14`, `17`, `20`, or `23` as needed. +Add `-DNO_STL=ON` to build without the standard library. + +### Using the run-tests script + +The repository also provides a convenience script in `test/`: + +```bash +cd test +./run-tests.sh [optimisation] [threads] [sanitizer] [compiler] [verbose] +``` + +| Argument | Values | Default | +|---|---|---| +| C++ standard | `11`, `14`, `17`, `20`, `23` | *(required)* | +| Optimisation | `0`, `1`, `2`, `3` | `0` | +| Threads | any integer | `4` | +| Sanitizer | `s` (enable) / `n` (disable) | `n` | +| Compiler | `gcc` / `clang` | all | +| Verbose | `v` (enable) / `n` (disable) | `n` | + +Example – run C++17 tests at `-O2` with 8 threads using GCC: + +```bash +./run-tests.sh 17 2 8 n gcc n +``` + +## Formatting Inside the Container + +The default container ships with **clang-format 18** and **treefmt**. +See [source-formatting.md](source-formatting.md) for the full formatting guide. + +Quick reference: + +```bash +# Format all tracked C/C++ files with treefmt +treefmt + +# Or use clang-format directly via the wrapper +./scripts/clang-format-wrapper -i include/etl/*.h +``` + +The wrapper script `scripts/clang-format-wrapper` resolves the correct +clang-format binary (prefers `clang-format-18`, falls back to `clang-format` +after checking the major version). + +## Customisation + +To add extra packages or tools to the default container, edit +`.devcontainer/Dockerfile`. The image follows a straightforward +`apt-get install` pattern, so adding a new package is as simple as appending +it to the existing `apt-get` line. + +To create a new compiler variant: + +1. Create a folder under `.devcontainer/` (e.g. `.devcontainer/gcc16/`). +2. Add a `devcontainer.json` that references `"../Dockerfile"` and sets + `BASE_IMAGE_NAME` to the desired image (e.g. `gcc:16`). +3. Set `DEBIAN_SNAPSHOT` to `"none"` for upstream compiler images. + +Example: + +```jsonc +{ + "name": "Gcc 16", + "build": { + "dockerfile": "../Dockerfile", + "args": { + "BASE_IMAGE_NAME": "gcc:16", + "DEBIAN_SNAPSHOT": "none" + }, + "context": "../context" + } +} +``` + +## Troubleshooting + +| Symptom | Cause / Fix | +|---|---| +| `apt-get` fails with *"Release file … is not valid yet"* | The Debian snapshot timestamp is in the future relative to the build host clock. Either update `DEBIAN_SNAPSHOT` in `devcontainer.json` or set it to `"none"`. | +| `clang-format` reports the wrong version | The wrapper expects version **18**. Make sure the image installs `clang-format` (or `clang-format-18`) and that the binary is on `PATH`. | +| Permission errors on mounted files | The `run-docker.sh` script runs as user `vscode`. Ensure your host UID matches, or adjust the `--user` flag. | +| s390x tests crash immediately | Verify that `qemu-user-static` is installed and that `binfmt-support` is active. On some hosts you may need to register binfmt handlers with `docker run --privileged --rm tonistiigi/binfmt --install all`. | +| Build is very slow the first time | Docker is downloading and building the image from scratch. Subsequent builds use the layer cache and are much faster. | diff --git a/docs/format.md b/docs/format.md new file mode 100644 index 00000000..1f3a5e37 --- /dev/null +++ b/docs/format.md @@ -0,0 +1,382 @@ +# ETL Format & Print + +## 1. Overview + +ETL provides text formatting facilities modelled on C++20 `std::format` and C++23 +`std::print`. They allow type-safe, positional formatting of values into strings +or directly to a character output device — without heap allocation. + +**Minimum language standard:** C++11 (`ETL_USING_CPP11`). + +**Headers:** + +| Header | Provides | +|---|---| +| `etl/format.h` | `etl::format_to`, `etl::format_to_n`, `etl::formatted_size` | +| `etl/print.h` | `etl::print`, `etl::println` (includes `etl/format.h`) | + +## 2. `etl::format_to` + +### Generic output-iterator overload + +```cpp +template +OutputIt format_to(OutputIt out, format_string fmt, Args&&... args); +``` + +Formats `args` according to the format string `fmt` and writes the result through +the output iterator `out`. Returns an iterator past the last character written. + +`OutputIt` can be any output iterator whose dereferenced type is assignable from +`char`, for example `etl::istring::iterator` or +`etl::back_insert_iterator`. + +```cpp +etl::string<100> s; + +// Using a raw iterator — you must resize the string yourself +etl::istring::iterator result = etl::format_to(s.begin(), "{0} {1}", 34, 56); +s.uninitialized_resize(static_cast(result - s.begin())); +// s == "34 56" + +// Using a back_insert_iterator — string grows automatically +s.clear(); +etl::back_insert_iterator it(s); +etl::format_to(it, "{} {}", 65, 34); +// s == "65 34" +``` + +### `etl::istring&` overload (ETL-specific) + +```cpp +template +etl::istring::iterator format_to(etl::istring& out, + format_string fmt, + Args&&... args); +``` + +Convenience overload that writes into an `etl::istring` (or any derived +`etl::string`). The string is automatically resized to the number of +characters written, up to `out.max_size()`. Returns an iterator past the +last character written. + +```cpp +etl::string<100> s; +etl::format_to(s, "Hello, {}!", "world"); +// s == "Hello, world!" +``` + +### `etl::format_to_n` + +```cpp +template +OutputIt format_to_n(OutputIt out, size_t n, + format_string fmt, Args&&... args); +``` + +Like `format_to`, but writes **at most** `n` characters. Characters beyond the +limit are silently discarded. + +```cpp +etl::string<10> s = "abcdefghij"; +etl::format_to_n(s.begin(), 3, "xy{}", 123); +// s == "xy1defghij" (only 3 chars written) +``` + +## 3. `etl::formatted_size` + +```cpp +template +size_t formatted_size(format_string fmt, Args&&... args); +``` + +Returns the total number of characters that `format_to` would produce, without +actually writing anything. Useful for pre-computing buffer sizes. + +```cpp +size_t n; +n = etl::formatted_size(""); // 0 +n = etl::formatted_size("{}", ""); // 0 +n = etl::formatted_size("xyz{}", 12); // 5 +n = etl::formatted_size("{}", "abc"); // 3 +``` + +## 4. `etl::print` and `etl::println` + +Declared in `etl/print.h`. + +### `etl::print` + +```cpp +template +void print(etl::format_string fmt, Args&&... args); +``` + +Formats the arguments and outputs each character by calling `etl_putchar()`. + +### `etl::println` + +```cpp +// With arguments — prints formatted text followed by '\n' +template +void println(etl::format_string fmt, Args&&... args); + +// Without arguments — prints a bare newline +void println(); +``` + +### Implementing `etl_putchar` + +`etl/print.h` declares (but does not define) the following C-linkage function: + +```cpp +extern "C" void etl_putchar(int c); +``` + +You **must** provide a definition in your project. The `int` parameter follows +the convention of the standard `putchar()` and carries a single `char` value. + +Typical implementations forward to a UART, a debug probe, `putchar`, or any +other single-character output sink: + +```cpp +// Example: forward to standard putchar +extern "C" void etl_putchar(int c) +{ + putchar(c); +} +``` + +### Example + +```cpp +etl::print("x = {}, y = {}\n", 10, 20); // "x = 10, y = 20\n" +etl::println("Hello, {}!", "world"); // "Hello, world!\n" +etl::println(); // "\n" +``` + +## 5. Format String Syntax + +A format string is ordinary text with **replacement fields** delimited by braces: + +``` +"literal text {} more text {1:>10} end" +``` + +### Replacement field grammar + +``` +replacement_field ::= '{' [arg_id] [':' format_spec] '}' +arg_id ::= integer // e.g. 0, 1, 2 … +format_spec ::= [[fill]align] [sign] ['#'] ['0'] [width] ['.' precision] ['L'] [type] +``` + +| Component | Syntax | Description | +|---|---|---| +| **Argument index** | `{0}`, `{1}`, … | Manual positional indexing. Cannot be mixed with automatic indexing. | +| **Automatic index** | `{}` | Uses the next argument in order. Cannot be mixed with manual indexing. | +| **Fill character** | any character except `{` or `}` | Used together with an alignment specifier. Default is space (` `). | +| **Alignment** | `<` left, `>` right, `^` center | Aligns the formatted value within the given *width*. | +| **Sign** | `+` always, `-` negative only (default), ` ` space for positive | Controls sign display for numeric types. | +| **`#` (alt form)** | `#` | Adds `0x`/`0X` for hex, `0b`/`0B` for binary, `0` for octal. | +| **`0` (zero-pad)** | `0` | Pads the number with leading zeros (after sign/prefix). | +| **Width** | integer, or `{}` / `{n}` | Minimum field width. Supports nested replacement fields for dynamic width. | +| **Precision** | `.` integer, or `.{}` / `.{n}` | For strings: maximum characters to output. For floats: number of decimal digits. Supports nested replacement fields. | +| **`L`** | `L` | Locale-specific flag (parsed but currently ignored). | +| **Type** | see [Presentation Types](#7-presentation-types-per-argument-kind) | Selects the output representation. | + +### Examples + +```cpp +etl::format_to(s, "{:>10}", 42); // " 42" +etl::format_to(s, "{:*^10}", 42); // "****42****" +etl::format_to(s, "{:+05d}", 67); // "+00067" +etl::format_to(s, "{:#x}", 0x3f4); // "0x3f4" +etl::format_to(s, "{:.3s}", "abcdef"); // "abc" +etl::format_to(s, "{1} {0}", 1, 2); // "2 1" +``` + +## 6. Supported Argument Types + +The core set of formattable types (matching `std::basic_format_arg`): + +| Category | Types | +|---|---| +| Boolean | `bool` | +| Character | `char` | +| Signed integer | `int`, `long long int` | +| Unsigned integer | `unsigned int`, `unsigned long long int` | +| Floating-point *(opt-in)* | `float`, `double`, `long double` — requires `ETL_USING_FORMAT_FLOATING_POINT` | +| String | `const char*`, `etl::string_view` | +| Pointer | `const void*` | + +### Implicit conversions + +Types not listed above are converted automatically before formatting: + +| Source type | Stored as | +|---|---| +| `short` | `int` | +| `unsigned short`, `uint16_t` | `unsigned int` | +| `long int` | `int` or `long long int` (platform-dependent) | +| `unsigned long int`, `size_t` | `unsigned int` or `unsigned long long int` | +| `int8_t` (`signed char`) | `char` | +| `uint8_t` (`unsigned char`) | `char` | +| `int16_t` | `int` | +| `uint32_t` | `unsigned int` | +| `int32_t` | `int` | +| `etl::string` | `etl::string_view` (lifetime of the temporary is guaranteed) | +| any pointer `T*` | `const void*` | + +## 7. Presentation Types per Argument Kind + +### Integers (`int`, `unsigned int`, `long long int`, `unsigned long long int`) + +| Type | Meaning | Example | +|---|---|---| +| `d` *(default)* | Decimal | `134` → `"134"` | +| `x` | Lowercase hexadecimal | `0x3f4` → `"3f4"` | +| `X` | Uppercase hexadecimal | `0x3f4` → `"3F4"` | +| `o` | Octal | `034` → `"34"` | +| `b` | Lowercase binary | `0b1010` → `"1010"` | +| `B` | Uppercase binary | `0b1010` → `"1010"` | +| `c` | Character (value as char) | `67` → `"C"` | + +With `#`: prefixes `0x`/`0X`, `0b`/`0B`, or leading `0` for octal. + +### Characters (`char`, `signed char`, `unsigned char`) + +| Type | Meaning | Example | +|---|---|---| +| `c` *(default)* | Character itself | `'s'` → `"s"` | +| `?` | Debug / escaped | `'\n'` → `"'\\n'"` | +| `d` | Decimal code point | `'a'` → `"97"` | +| `x` / `X` | Hex code point | `'a'` → `"61"` | + +### Booleans (`bool`) + +| Type | Meaning | Example | +|---|---|---| +| *(default)* | `false` / `true` | `true` → `"true"` | +| `s` | Same as default | `true` → `"true"` | +| `d` | `0` / `1` | `true` → `"1"` | +| `x` / `X` | Hex `0` / `1` | `true` → `"1"` | +| `o` | Octal (with `#`: `01`) | `true` → `"01"` | + +### Strings (`const char*`, `etl::string_view`, `etl::string`) + +| Type | Meaning | Example | +|---|---|---| +| `s` *(default)* | String output | `"data1"` → `"data1"` | +| `?` | Debug / escaped | `"data1\n"` → `"\"data1\\n\""` | + +Width and precision apply: width sets the minimum field width; precision (`.N`) +truncates the string to at most *N* characters. + +```cpp +etl::format_to(s, "{:>10s}", "data1"); // " data1" +etl::format_to(s, "{:.3s}", "abcdef"); // "abc" +etl::format_to(s, ".{:^8.3s}!", "data1"); // ". dat !" +``` + +### Pointers (`const void*`) + +| Type | Meaning | Example | +|---|---|---| +| `p` *(default)* | Lowercase hex with `0x` prefix | `nullptr` → `"0x0"` | +| `P` | Uppercase hex with `0X` prefix | `nullptr` → `"0X0"` | + +### Floating-point (`float`, `double`, `long double`) + +Requires `ETL_USING_FORMAT_FLOATING_POINT`. + +| Type | Meaning | Example | +|---|---|---| +| *(default)* | Shortest representation | `1.5f` → `"1.5"` | +| `e` / `E` | Scientific notation | `1.0f` → `"1.000000e+00"` | +| `f` / `F` | Fixed-point notation | `1.125f` → `"1.125000"` | +| `g` / `G` | General (fixed or scientific) | `1e10f` → `"1.000000e+10"` | +| `a` / `A` | Hexadecimal floating-point | `1.5f` → `"0x1.8p+0"` | + +`nan`, `inf` (lowercase for `e`/`f`/`g`/`a`, uppercase for `E`/`F`/`G`/`A`). + +## 8. Escape Sequences and Literal Braces + +### Literal braces + +Because `{` and `}` delimit replacement fields, they must be escaped by +doubling: + +| Input | Output | +|---|---| +| `{{` | `{` | +| `}}` | `}` | + +```cpp +etl::format_to(s, "abc{{def"); // "abc{def" +etl::format_to(s, "}}abc"); // "}abc" +``` + +### Debug / escaped presentation (`?`) + +The `?` type specifier produces a debug representation: + +- **Characters** are wrapped in single quotes with C-style escape sequences: + + | Character | Output | + |---|---| + | `\t` | `'\\t'` | + | `\n` | `'\\n'` | + | `\r` | `'\\r'` | + | `"` | `'\\\"'` | + | `'` | `'\\''` | + | `\\` | `'\\\\'` | + +- **Strings** are wrapped in double quotes with the same escape sequences: + + ```cpp + etl::format_to(s, "{:?}", "data1\n"); // "\"data1\\n\"" + ``` + +## 9. Error Handling + +Invalid format strings cause an `etl::bad_format_string_exception` (derived from +`etl::format_exception`, which is derived from `etl::exception`). + +Common error conditions: + +| Condition | Example | +|---|---| +| Missing closing brace | `"a{b"` | +| Unescaped `}` without matching `{` | `"a}b"` | +| Invalid characters inside `{}` | `"a{b}"` | +| Argument index out of range | `"{1}"` with only one argument | +| Mixing manual and automatic indexing | `"{0} {}"` | +| Invalid type specifier for the argument | `"{:d}"` on a `string_view` | +| Double colon in format spec | `"{::}"` | +| Precision on an integer | `"{:+#05.5X}"` on an `int` | + +```cpp +etl::string<100> s; +// These all throw etl::bad_format_string_exception: +etl::format_to(s, "a{b}", 1); // bad index spec +etl::format_to(s, "a{b", 1); // closing brace missing +etl::format_to(s, "a}b"); // unescaped } +etl::format_to(s, "{:d}", sv); // invalid type for string_view +``` + +> **Note:** On C++20 and later, compile-time format string validation through +> `consteval` is planned but not yet fully implemented. + +## 10. Differences from `std::format` + +| Area | `std::format` (C++20/23) | ETL | +|---|---|---| +| **Output target** | Returns `std::string` | Writes through an output iterator or into `etl::istring&` — no heap allocation. | +| **`etl::istring&` overload** | Not available | `format_to(etl::istring&, ...)` automatically resizes the string. | +| **`print` / `println` output** | Writes to `FILE*` / `stdout` | Writes character-by-character via user-defined `etl_putchar(int)`. | +| **Floating-point support** | Always available | Opt-in via `ETL_USING_FORMAT_FLOATING_POINT`. | +| **User-defined formatters** | `std::formatter` specialisations | Not yet supported. | +| **Locale** | `L` flag uses `std::locale` | `L` flag is parsed but has no effect. | +| **Compile-time validation** | Enforced via `consteval` on C++20 | Planned; currently validates at run time and throws `etl::bad_format_string_exception`. | +| **`format_to_n` return type** | `std::format_to_n_result` | Returns the underlying `OutputIt` directly. | diff --git a/docs/generators.md b/docs/generators.md new file mode 100644 index 00000000..d44a38b6 --- /dev/null +++ b/docs/generators.md @@ -0,0 +1,190 @@ +# Code Generation for Pre-C++11 Support + +ETL supports C++03 (also referred to as C++98) environments where variadic +templates, `constexpr`, and other modern features are unavailable. To +provide equivalent functionality, certain headers are **generated** using +[Cog](https://nedbatchelder.com/code/cog/), a Python-based code generation +tool that embeds Python snippets inside source files. + +This document explains how the code generation system works and how to +regenerate the headers if you modify a generator template. + +--- + +## Overview + +| Directory | Contents | +|---|---| +| `include/etl/generators/` | Generator templates (`*_generator.h`) and batch scripts | +| `include/etl/private/` | Generated output (`*_cpp03.h`) committed to the repository | +| `scripts/generator_test.py` | CI script that verifies generators match committed files | + +The generator templates contain embedded Python code (delimited by `[[[cog` +and `]]]`) that produces the repetitive C++03 boilerplate. Cog processes +these templates and writes the expanded output to `include/etl/private/`. + +--- + +## Generated Headers + +The following C++03 compatibility headers are generated: + +| Generator | Output | Purpose | +|---|---|---| +| `fsm_fwd_decl_cpp03_generator.h` | `fsm_fwd_decl_cpp03.h` | FSM forward declarations | +| `fsm_friend_decl_cpp03_generator.h` | `fsm_friend_decl_cpp03.h` | FSM friend declarations | +| `fsm_cpp03_generator.h` | `fsm_cpp03.h` | Finite state machine implementation | +| `message_router_cpp03_generator.h` | `message_router_cpp03.h` | Message router | +| `message_packet_cpp03_generator.h` | `message_packet_cpp03.h` | Message packet | +| `largest_type_cpp03_generator.h` | `largest_type_cpp03.h` | Largest type metafunction | +| `largest_alignment_cpp03_generator.h` | `largest_alignment_cpp03.h` | Largest alignment metafunction | +| `largest_cpp03_generator.h` | `largest_cpp03.h` | Largest type/size utilities | +| `smallest_cpp03_generator.h` | `smallest_cpp03.h` | Smallest type/size utilities | +| `type_traits_cpp03_generator.h` | `type_traits_cpp03.h` | Type traits (`is_one_of`, etc.) | +| `type_lookup_cpp03_generator.h` | `type_lookup_cpp03.h` | Type lookup metafunction | +| `type_select_cpp03_generator.h` | `type_select_cpp03.h` | Type selection metafunction | +| `variant_pool_cpp03_generator.h` | `variant_pool_cpp03.h` | Variant pool | + +--- + +## Generator Parameters + +Cog variables control how many template parameter overloads are generated: + +| Variable | Default | Used by | +|---|---|---| +| `Handlers` | 16 | FSM and message router generators | +| `NTypes` | 16 | Type utility generators (largest, smallest, lookup, select, variant pool) | +| `IsOneOf` | 16 | Type traits generator (`is_one_of`) | + +These defaults produce overloads supporting up to 16 types or handlers, +which is sufficient for most embedded applications while keeping compile +times reasonable. + +--- + +## Prerequisites + +* **Python 3** +* **cogapp** – install via: + + ```bash + pip install cogapp + ``` + +--- + +## Regenerating Headers + +### Using the batch scripts (Windows) + +Each generator has a corresponding `.bat` file in `include/etl/generators/`: + +```bat +cd include/etl/generators +generate.bat # Regenerate all headers +generate_fsm.bat # Regenerate FSM headers only +generate_smallest.bat # Regenerate smallest_cpp03.h only +# etc. +``` + +### Manual invocation + +Run Cog directly from the `include/etl/generators/` directory: + +```bash +cd include/etl/generators + +# Example: regenerate smallest_cpp03.h +python3 -m cogapp -d -e -o../private/smallest_cpp03.h -DNTypes=16 smallest_cpp03_generator.h + +# Example: regenerate fsm_cpp03.h +python3 -m cogapp -d -e -o../private/fsm_cpp03.h -DHandlers=16 fsm_cpp03_generator.h +``` + +Cog options used: + +| Option | Meaning | +|---|---| +| `-d` | Delete the generator markers from output | +| `-e` | Warn if the input file has no generator markers | +| `-o` | Write output to the specified file | +| `-D=` | Define a Cog variable | + +### Regenerating all headers + +The `generate.bat` script regenerates every header: + +```bash +cd include/etl/generators +./generate.bat # Windows +# or run the commands manually on Linux/macOS +``` + +On Linux/macOS you can run the commands from `generate.bat` directly in +your shell (they are standard `python3 -m cogapp` invocations). + +--- + +## Verifying Generators + +After modifying a generator template, verify the output matches the +committed file: + +```bash +python3 scripts/generator_test.py +``` + +This script: + +1. Runs Cog on every `*_generator.h` file. +2. Compares each output against the corresponding file in + `include/etl/private/`. +3. Reports success or failure. + +The `generator.yml` GitHub Actions workflow runs this automatically on +every push and pull request. + +--- + +## How Generators Work + +A generator template contains standard C++ code interspersed with Cog +directives. For example, from `smallest_cpp03_generator.h`: + +```cpp +/*[[[cog +import cog +cog.outl("template " % int(NTypes)) +]]]*/ +// Generated code appears here after running Cog +/*[[[end]]]*/ +``` + +When Cog processes this file with `-DNTypes=16`, the Python code executes +and outputs the expanded template parameter list supporting 16 types. + +--- + +## Adding a New Generator + +1. Create `include/etl/generators/_cpp03_generator.h` with Cog + directives. +2. Add a corresponding entry to `generate.bat`. +3. Run `generate.bat` (or the equivalent Cog command) to produce + `include/etl/private/_cpp03.h`. +4. Commit both the generator and the generated output. +5. Verify with `python3 scripts/generator_test.py`. + +--- + +## Troubleshooting + +| Problem | Solution | +|---|---| +| `ModuleNotFoundError: No module named 'cogapp'` | Install Cog: `pip install cogapp` | +| Generator output differs from committed file | Regenerate and commit the updated output | +| Need more than 16 types/handlers | Change `-DNTypes=` or `-DHandlers=` and regenerate | diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 00000000..c6773f6f --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,412 @@ +# Testing ETL + +This document describes how to build and run the ETL test suite locally, +inside Dev Containers, and in CI. + +## Table of Contents + +1. [Prerequisites](#prerequisites) +2. [Running Tests Locally (`test/run-tests.sh`)](#running-tests-locally) +3. [Syntax Checks (`test/run-syntax-checks.sh`)](#syntax-checks) +4. [Cross-Architecture Testing (`.devcontainer/run-tests.sh`)](#cross-architecture-testing) +5. [Dev Containers for Native Compilers](#dev-containers-for-native-compilers) +6. [CMake Options Reference](#cmake-options-reference) +7. [CI Checks (GitHub Actions)](#ci-checks-github-actions) +8. [Appveyor (Windows / MSVC)](#appveyor-windows--msvc) +9. [Code Coverage](#code-coverage) +10. [Generator Tests (`scripts/generator_test.py`)](#generator-tests) + +--- + +## Prerequisites + +* **CMake** ≥ 3.10 +* **GCC** and/or **Clang** (any version supported by the project) +* **Make** or **Ninja** (build backend) +* **Docker** (only needed for cross-architecture testing via `.devcontainer/run-tests.sh`) +* **QEMU user-mode** (installed automatically inside the cross-arch Docker images) + +The project is header-only, so there is no library to compile – the build +step compiles the test binary `etl_tests` which links against a bundled copy +of **UnitTest++**. + +--- + +## Running Tests Locally + +The main entry point for local testing is **`test/run-tests.sh`**. It +iterates over a matrix of compiler / configuration combinations, creates a +temporary `build-make` directory for each one, runs CMake + Make + CTest, +and reports coloured pass/fail output (also appended to `log.txt`). + +### Synopsis + +```bash +cd test +./run-tests.sh [Optimisation] [Threads] [Sanitizer] [Compiler] [Verbose] +``` + +| Argument | Values | Default | +|---|---|---| +| C++ Standard | `11`, `14`, `17`, `20`, `23`, or `all` | *(required)* | +| Optimisation | `0`, `1`, `2`, `3` | `0` | +| Threads | any positive integer | `4` | +| Sanitizer | `s` (enable) / `n` (disable) | `n` (disabled) | +| Compiler | `gcc`, `clang` | all compilers | +| Verbose | `v` (enable) / `n` (disable) | `n` (disabled) | + +### Examples + +```bash +# Run all C++17 tests with GCC only, optimisation -O0, 8 threads +./run-tests.sh 17 0 8 n gcc + +# Run every standard with both compilers, sanitizers enabled, verbose +./run-tests.sh all 0 4 s "" v +``` + +### What the script does + +For every selected C++ standard the script loops over a built-in list of +configurations (STL / No STL / Force C++03 / Non-virtual messages / …) for +each selected compiler. For every combination it: + +1. Creates a fresh `build-make` directory inside the configuration's source + subdirectory. +2. Invokes `cmake` with the appropriate `-D` flags (see + [CMake Options Reference](#cmake-options-reference)). +3. Builds via `cmake --build .` (parallel level controlled by + `CMAKE_BUILD_PARALLEL_LEVEL`). +4. Runs `ctest -V`. +5. Reports success or failure and removes the build directory. + +The script exits immediately on the first compilation or test failure. + +### Test configurations exercised + +| Compiler | Configuration | +|---|---| +| GCC | STL | +| GCC | STL – Non-virtual messages | +| GCC | STL – Force C++03 | +| GCC | No STL | +| GCC | No STL – Force C++03 | +| GCC | No STL – Builtin mem functions | +| Clang | STL | +| Clang | STL – Force C++03 | +| Clang | No STL | +| Clang | No STL – Force C++03 | +| Clang | No STL – Builtin mem functions | +| GCC / Clang | Initializer list test | +| GCC / Clang | Error macros – log_errors, exceptions, log_errors_and_exceptions, assert_function | + +--- + +## Syntax Checks + +The script **`test/run-syntax-checks.sh`** performs compilation-only syntax +checks across multiple C++ standards and configurations. Unlike +`run-tests.sh`, it **does not run the test binary** – it only verifies that +the code compiles successfully. This is useful for quickly validating that +header changes do not introduce compilation errors across the supported +standard/configuration matrix. + +### Synopsis + +```bash +cd test +./run-syntax-checks.sh [Threads] [Compiler] +``` + +| Argument | Values | Default | +|---|---|---| +| C++ Standard | `03`, `11`, `14`, `17`, `20`, `23`, or `a` (all) | *(required)* | +| Threads | any positive integer | `4` | +| Compiler | `gcc`, `clang` | all compilers | + +### Examples + +```bash +# Check C++17 syntax with GCC only, using 8 threads +./run-syntax-checks.sh 17 8 gcc + +# Check all standards with both compilers +./run-syntax-checks.sh a +``` + +### What the script does + +The script operates from the `test/syntax_check` directory and iterates over +the selected C++ standard(s). For each standard and compiler combination it: + +1. Creates fresh build directories (`bgcc` / `bclang`). +2. Invokes `cmake` with the appropriate `-D` flags for the configuration. +3. Builds via `cmake --build`. +4. Reports compilation success or failure (logged to `log.txt`). + +The script exits immediately on the first compilation failure. + +### Configurations checked per standard + +For each C++ standard the following configurations are compiled: + +| Compiler | Configuration | +|---|---| +| GCC | STL | +| GCC | No STL | +| GCC | STL – Built-in traits | +| GCC | No STL – Built-in traits | +| Clang | STL | +| Clang | No STL | +| Clang | STL – Built-in traits | +| Clang | No STL – Built-in traits | + +--- + +## Cross-Architecture Testing + +**`.devcontainer/run-tests.sh`** builds and runs the test suite for +non-x86_64 architectures using Docker and QEMU user-mode emulation. It is +designed to be run **from the project root**. + +### Supported architectures + +| Argument | Target | Endianness | QEMU binary | +|---|---|---|---| +| `armhf` | ARM hard-float (32-bit) | Little | `qemu-arm-static` | +| `i386` | x86 32-bit | Little | `qemu-i386-static` | +| `powerpc` | PowerPC 32-bit | Big | `qemu-ppc` | +| `riscv64` | RISC-V 64-bit | Little | `qemu-riscv64-static` | +| `s390x` | IBM Z (64-bit) | Big | `qemu-s390x-static` | + +### Synopsis + +```bash +# From the project root +.devcontainer/run-tests.sh +``` + +### How it works + +The script has two phases controlled by a second (internal) argument: + +1. **Outside the container** (no second argument): + * Builds a Docker image from `.devcontainer//Dockerfile`. + * Starts a container, bind-mounting the project at `/workspaces/etl`. + * Re-invokes itself *inside* the container with the `inside_container` + flag. + +2. **Inside the container** (`inside_container`): + * Creates `build-` and runs CMake with the appropriate cross- + compilation toolchain file + (`.devcontainer//toolchain-.cmake`). + * Builds with `cmake --build .` using all available cores. + * Runs the test suite via `ctest --output-on-failure`. + +The toolchain files set `CMAKE_CROSSCOMPILING_EMULATOR` so that CTest can +run the binary transparently through QEMU. + +### Example + +```bash +# Build & run the armhf test suite +.devcontainer/run-tests.sh armhf +``` + +The cross-arch containers build with the following fixed settings: + +* C++23, No STL, sanitizer off, optimisation -O0. + +--- + +## Dev Containers for Native Compilers + +The `.devcontainer/` directory also provides Dev Container definitions for a +wide range of **native** (x86_64) compiler versions. These are intended for +use with **VS Code Dev Containers** or **GitHub Codespaces**. + +| Directory | Compiler | +|---|---| +| `gcc09` – `gcc15` | GCC 9 through 15 | +| `clang7` – `clang21` | Clang 7 through 21 | + +Each subdirectory contains a `devcontainer.json` that references the shared +`Dockerfile` (`.devcontainer/Dockerfile`) and passes the appropriate base +Docker image via the `BASE_IMAGE_NAME` build argument (e.g. `gcc:15`). + +The default Dev Container (`.devcontainer/devcontainer.json`) uses the +Microsoft C++ dev-container base image. + +To use one of these containers: + +1. Open the repository in VS Code. +2. **Ctrl+Shift+P → Dev Containers: Reopen in Container** and select the + desired configuration (e.g. *Gcc 15*). +3. Use `test/run-tests.sh` inside the container as described above. + +--- + +## CMake Options Reference + +When invoking CMake for the test suite (source directory is `test/`), the +following `-D` options control the build: + +| Option | Type | Description | +|---|---|---| +| `BUILD_TESTS` | `BOOL` | Must be `ON` to compile the test binary. | +| `NO_STL` | `BOOL` | Build without the C++ Standard Library. | +| `ETL_CXX_STANDARD` | `STRING` | C++ standard: `11`, `14`, `17`, `20`, `23`. | +| `ETL_OPTIMISATION` | `STRING` | Compiler optimisation flag, e.g. `-O0`. | +| `ETL_ENABLE_SANITIZER` | `BOOL` | Enable address / undefined-behaviour sanitizers. | +| `ETL_USE_TYPE_TRAITS_BUILTINS` | `BOOL` | Use compiler built-in type traits. | +| `ETL_USER_DEFINED_TYPE_TRAITS` | `BOOL` | Use user-defined type traits. | +| `ETL_FORCE_TEST_CPP03_IMPLEMENTATION` | `BOOL` | Force the C++03 code paths even on newer standards. | +| `ETL_MESSAGES_ARE_NOT_VIRTUAL` | `BOOL` | Use non-virtual message types. | +| `ETL_USE_BUILTIN_MEM_FUNCTIONS` | `BOOL` | Use built-in memory functions in No-STL mode. | +| `CMAKE_TOOLCHAIN_FILE` | `PATH` | Toolchain file for cross-compilation. | + +### Minimal manual build example + +```bash +cd test +mkdir build && cd build +cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_CXX_STANDARD=20 .. +cmake --build . -j$(nproc) +ctest -V +``` + +--- + +## CI Checks (GitHub Actions) + +Every push or pull request to `master`, `development`, or `pull-request/*` +branches triggers a comprehensive set of GitHub Actions workflows defined in +`.github/workflows/`. + +### Workflow matrix + +| Workflow file | Compiler | Standard | Notes | +|---|---|---|---| +| `gcc-c++11.yml` | GCC | C++11 | STL, No STL, Force C++03 | +| `gcc-c++14.yml` | GCC | C++14 | STL, No STL, Force C++03 | +| `gcc-c++17.yml` | GCC | C++17 | STL, No STL, Force C++03 | +| `gcc-c++20.yml` | GCC | C++20 | STL, No STL, Force C++03 | +| `gcc-c++23.yml` | GCC | C++23 | STL, No STL, Force C++03 | +| `clang-c++11.yml` | Clang | C++11 | STL, No STL, Force C++03 | +| `clang-c++14.yml` | Clang | C++14 | STL, No STL, Force C++03 | +| `clang-c++17.yml` | Clang | C++17 | STL, No STL, Force C++03 | +| `clang-c++20.yml` | Clang | C++20 | STL, No STL, Force C++03 | +| `clang-c++23.yml` | Clang | C++23 | STL, No STL, Force C++03 | +| `gcc-syntax-checks.yml` | GCC | C++03 – C++23 | Compilation-only syntax checks (no tests run) | +| `clang-syntax-checks.yml` | Clang | C++03 – C++23 | Compilation-only syntax checks (no tests run) | +| `msvc.yml` | MSVC 2022 | C++17 | Windows, STL & No STL | +| `gcc-c++23-armhf.yml` | GCC cross | C++23 | armhf via QEMU | +| `gcc-c++23-i386.yml` | GCC cross | C++23 | i386 via QEMU | +| `gcc-c++23-powerpc.yml` | GCC cross | C++23 | powerpc via QEMU | +| `gcc-c++23-riscv64.yml` | GCC cross | C++23 | RISC-V 64 via QEMU | +| `gcc-c++23-s390x.yml` | GCC cross | C++23 | s390x via QEMU | +| `coverage.yml` | GCC | — | Generates lcov coverage report, deploys to GitHub Pages | +| `generator.yml` | — | — | Runs the code generator | +| `platformio-update.yml` | — | — | PlatformIO registry update | + +### Typical CI job structure + +Each compiler/standard workflow follows the same pattern: + +1. **Checkout** – `actions/checkout@v4`. +2. **Build** – set `CC`/`CXX`, call `cmake` with the appropriate `-D` flags, + then `make -j`. +3. **Run tests** – execute `./test/etl_tests -v` (or `ctest -V` for cross- + arch jobs). + +The cross-architecture CI jobs additionally install a cross-compiler +toolchain and QEMU inside a `debian:trixie` container, use the matching +toolchain file from `.devcontainer//`, and run tests via CTest (which +delegates to QEMU through `CMAKE_CROSSCOMPILING_EMULATOR`). + +### Branches tested + +* `master` +* `development` +* `pull-request/*` + +All workflows run on both `push` and `pull_request` events (types: opened, +synchronize, reopened). + +--- + +## Appveyor (Windows / MSVC) + +The `appveyor.yml` at the repository root provides additional Windows CI +using **Visual Studio 2022**. It builds the `master` branch only. + +Configurations tested: + +* Debug MSVC C++14 +* Debug MSVC C++14 – No STL +* Debug MSVC C++17 +* Debug MSVC C++17 – No STL +* Debug MSVC C++20 +* Debug MSVC C++20 – No STL + +The build uses the VS 2022 solution file at `test/vs2022/etl.vcxproj`. + +--- + +## Code Coverage + +The `coverage.yml` GitHub Actions workflow generates an **lcov** coverage +report: + +1. Runs `test/run-coverage.sh` which builds and tests with GCC coverage + flags. +2. Uploads the HTML report as a build artifact (retained for 30 days). +3. On pushes to `master`, deploys the report to **GitHub Pages**. + +To generate coverage locally: + +```bash +cd test +./run-coverage.sh +# Open test/build-coverage/coverage/index.html +``` + +--- + +## Generator Tests + +The script **`scripts/generator_test.py`** verifies that the code generators +in `include/etl/generators/` produce output matching the checked-in header +files in `include/etl/private/`. + +ETL uses [Cog](https://nedbatchelder.com/code/cog/) to generate certain +repetitive header files (e.g. `delegate.h`, `message_packet.h`). The +generator templates live in `include/etl/generators/*_generator.h` and the +generated output is committed to `include/etl/private/*.h`. This test +ensures the two stay in sync. + +### Prerequisites + +* **Python 3** +* **cogapp** – install via `pip install cogapp` + +### Synopsis + +```bash +python3 scripts/generator_test.py +``` + +### What the script does + +1. Iterates over every `*_generator.h` file in `include/etl/generators/`. +2. Runs Cog on each generator, outputting to `build/generator_tmp/`. +3. Compares each generated file against the corresponding file in + `include/etl/private/`. +4. Reports success if all files match, or failure if any differ. + +The script exits with code `0` on success and `1` on failure. + +### CI integration + +The `generator.yml` GitHub Actions workflow runs this script automatically +on pushes and pull requests to verify generator consistency. diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 63bfe13b..b1d570e2 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -558,7 +558,8 @@ namespace etl { while (first != last) { - *first = value; + // This cast is necessary because the signedness can differ + *first = static_cast::value_type>(value); ++first; } } @@ -898,6 +899,7 @@ namespace etl { TDistance parent = (value_index - 1) / 2; +#include "etl/private/diagnostic_array_bounds_push.h" while ((value_index > top_index) && compare(first[parent], value)) { first[value_index] = ETL_MOVE(first[parent]); @@ -906,6 +908,7 @@ namespace etl } first[value_index] = ETL_MOVE(value); +#include "etl/private/diagnostic_pop.h" } // Adjust Heap Helper @@ -1358,7 +1361,9 @@ namespace etl value_type temp(ETL_MOVE(*first)); // Move the rest. +#include "etl/private/diagnostic_stringop_overread_push.h" TIterator result = etl::move(etl::next(first), last, first); +#include "etl/private/diagnostic_pop.h" // Restore the first item in its rotated position. *result = ETL_MOVE(temp); @@ -2786,7 +2791,9 @@ namespace etl d_size_type d_size = etl::distance(o_begin, o_end); min_size_type min_size = etl::min(s_size, d_size); + #include "etl/private/diagnostic_null_dereference_push.h" return etl::move(i_begin, i_begin + min_size, o_begin); + #include "etl/private/diagnostic_pop.h" } //*************************************************************************** @@ -5860,12 +5867,14 @@ namespace etl } } + #include "etl/private/diagnostic_array_bounds_push.h" // Sort the heap to produce a sorted output range for (auto heap_end = heap_size - 1; heap_end > 0; --heap_end) { etl::iter_swap(result_first, result_first + heap_end); sift_down(result_first, decltype(heap_size){0}, heap_end, comp, proj2); } + #include "etl/private/diagnostic_pop.h" return {etl::move(in_last), etl::move(r)}; } @@ -6202,6 +6211,16 @@ namespace etl I left_partition = stable_partition_impl(first, middle, etl::ref(pred), etl::ref(proj), len / 2); I right_partition = stable_partition_impl(middle, last, etl::ref(pred), etl::ref(proj), len - len / 2); + if (left_partition == middle) + { + return right_partition; + } + + if (middle == right_partition) + { + return left_partition; + } + return etl::rotate(left_partition, middle, right_partition); } }; diff --git a/include/etl/atomic/atomic_gcc_sync.h b/include/etl/atomic/atomic_gcc_sync.h index 087489aa..425d8707 100644 --- a/include/etl/atomic/atomic_gcc_sync.h +++ b/include/etl/atomic/atomic_gcc_sync.h @@ -341,6 +341,68 @@ namespace etl return __atomic_fetch_xor(&value, v, order); } + // Fetch max + T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + T old = load(order); + + while (v > old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = load(order); + + while (v > old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + // Fetch min + T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + T old = load(order); + + while (v < old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = load(order); + + while (v < old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + // Exchange T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) { @@ -1234,6 +1296,72 @@ namespace etl return __sync_fetch_and_xor(&value, v); } + // Fetch max + T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + (void)order; + T old = load(order); + + while (v > old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_max(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + (void)order; + T old = load(order); + + while (v > old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + // Fetch min + T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + (void)order; + T old = load(order); + + while (v < old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_min(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + (void)order; + T old = load(order); + + while (v < old) + { + if (compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + // Exchange T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) { diff --git a/include/etl/atomic/atomic_std.h b/include/etl/atomic/atomic_std.h index ee765a70..06fcef6c 100644 --- a/include/etl/atomic/atomic_std.h +++ b/include/etl/atomic/atomic_std.h @@ -40,11 +40,98 @@ namespace etl { //*************************************************************************** // ETL Atomic type for compilers that support std::atomic. - // etl::atomic is a simple wrapper around std::atomic. + // etl::atomic is a wrapper around std::atomic that adds fetch_max and + // fetch_min if the standard library does not yet provide them. //*************************************************************************** +#if ETL_HAS_STD_ATOMIC_MIN_MAX + // The standard library already provides fetch_max/fetch_min. template using atomic = std::atomic; +#else + template + class atomic : public std::atomic + { + using base_type = std::atomic; + + public: + + atomic() ETL_NOEXCEPT = default; + + ETL_CONSTEXPR atomic(T desired) ETL_NOEXCEPT + : base_type(desired) + { + } + + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + using base_type::operator=; + + // Fetch max + T fetch_max(T v, std::memory_order order = std::memory_order_seq_cst) + { + T old = this->load(order); + + while (v > old) + { + if (this->compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_max(T v, std::memory_order order = std::memory_order_seq_cst) volatile + { + T old = this->load(order); + + while (v > old) + { + if (this->compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + // Fetch min + T fetch_min(T v, std::memory_order order = std::memory_order_seq_cst) + { + T old = this->load(order); + + while (v < old) + { + if (this->compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + + T fetch_min(T v, std::memory_order order = std::memory_order_seq_cst) volatile + { + T old = this->load(order); + + while (v < old) + { + if (this->compare_exchange_weak(old, v, order)) + { + break; + } + } + + return old; + } + }; +#endif using memory_order = std::memory_order; @@ -55,66 +142,66 @@ namespace etl static ETL_CONSTANT etl::memory_order memory_order_acq_rel = std::memory_order_acq_rel; static ETL_CONSTANT etl::memory_order memory_order_seq_cst = std::memory_order_seq_cst; - using atomic_bool = std::atomic; - using atomic_char = std::atomic; - using atomic_schar = std::atomic; - using atomic_uchar = std::atomic; - using atomic_short = std::atomic; - using atomic_ushort = std::atomic; - using atomic_int = std::atomic; - using atomic_uint = std::atomic; - using atomic_long = std::atomic; - using atomic_ulong = std::atomic; - using atomic_llong = std::atomic; - using atomic_ullong = std::atomic; - using atomic_wchar_t = std::atomic; + using atomic_bool = etl::atomic; + using atomic_char = etl::atomic; + using atomic_schar = etl::atomic; + using atomic_uchar = etl::atomic; + using atomic_short = etl::atomic; + using atomic_ushort = etl::atomic; + using atomic_int = etl::atomic; + using atomic_uint = etl::atomic; + using atomic_long = etl::atomic; + using atomic_ulong = etl::atomic; + using atomic_llong = etl::atomic; + using atomic_ullong = etl::atomic; + using atomic_wchar_t = etl::atomic; #if ETL_HAS_NATIVE_CHAR8_T - using atomic_char8_t = std::atomic; + using atomic_char8_t = etl::atomic; #endif #if ETL_HAS_NATIVE_CHAR16_T - using atomic_char16_t = std::atomic; + using atomic_char16_t = etl::atomic; #endif #if ETL_HAS_NATIVE_CHAR32_T - using atomic_char32_t = std::atomic; + using atomic_char32_t = etl::atomic; #endif #if ETL_USING_8BIT_TYPES - using atomic_uint8_t = std::atomic; - using atomic_int8_t = std::atomic; + using atomic_uint8_t = etl::atomic; + using atomic_int8_t = etl::atomic; #endif - using atomic_uint16_t = std::atomic; - using atomic_int16_t = std::atomic; - using atomic_uint32_t = std::atomic; - using atomic_int32_t = std::atomic; + using atomic_uint16_t = etl::atomic; + using atomic_int16_t = etl::atomic; + using atomic_uint32_t = etl::atomic; + using atomic_int32_t = etl::atomic; #if ETL_USING_64BIT_TYPES - using atomic_uint64_t = std::atomic; - using atomic_int64_t = std::atomic; + using atomic_uint64_t = etl::atomic; + using atomic_int64_t = etl::atomic; #endif - using atomic_int_least8_t = std::atomic; - using atomic_uint_least8_t = std::atomic; - using atomic_int_least16_t = std::atomic; - using atomic_uint_least16_t = std::atomic; - using atomic_int_least32_t = std::atomic; - using atomic_uint_least32_t = std::atomic; + using atomic_int_least8_t = etl::atomic; + using atomic_uint_least8_t = etl::atomic; + using atomic_int_least16_t = etl::atomic; + using atomic_uint_least16_t = etl::atomic; + using atomic_int_least32_t = etl::atomic; + using atomic_uint_least32_t = etl::atomic; #if ETL_USING_64BIT_TYPES - using atomic_int_least64_t = std::atomic; - using atomic_uint_least64_t = std::atomic; + using atomic_int_least64_t = etl::atomic; + using atomic_uint_least64_t = etl::atomic; #endif - using atomic_int_fast8_t = std::atomic; - using atomic_uint_fast8_t = std::atomic; - using atomic_int_fast16_t = std::atomic; - using atomic_uint_fast16_t = std::atomic; - using atomic_int_fast32_t = std::atomic; - using atomic_uint_fast32_t = std::atomic; + using atomic_int_fast8_t = etl::atomic; + using atomic_uint_fast8_t = etl::atomic; + using atomic_int_fast16_t = etl::atomic; + using atomic_uint_fast16_t = etl::atomic; + using atomic_int_fast32_t = etl::atomic; + using atomic_uint_fast32_t = etl::atomic; #if ETL_USING_64BIT_TYPES - using atomic_int_fast64_t = std::atomic; - using atomic_uint_fast64_t = std::atomic; + using atomic_int_fast64_t = etl::atomic; + using atomic_uint_fast64_t = etl::atomic; #endif - using atomic_intptr_t = std::atomic; - using atomic_uintptr_t = std::atomic; - using atomic_size_t = std::atomic; - using atomic_ptrdiff_t = std::atomic; - using atomic_intmax_t = std::atomic; - using atomic_uintmax_t = std::atomic; + using atomic_intptr_t = etl::atomic; + using atomic_uintptr_t = etl::atomic; + using atomic_size_t = etl::atomic; + using atomic_ptrdiff_t = etl::atomic; + using atomic_intmax_t = etl::atomic; + using atomic_uintmax_t = etl::atomic; } // namespace etl #endif diff --git a/include/etl/bip_buffer_spsc_atomic.h b/include/etl/bip_buffer_spsc_atomic.h index 0901af80..783e3ea6 100644 --- a/include/etl/bip_buffer_spsc_atomic.h +++ b/include/etl/bip_buffer_spsc_atomic.h @@ -404,7 +404,7 @@ namespace etl //************************************************************************* void read_commit(const span& reserve) { - size_type rindex = etl::distance(p_buffer, reserve.data()); + size_type rindex = static_cast(etl::distance(p_buffer, reserve.data())); apply_read_reserve(rindex, reserve.size()); } @@ -438,7 +438,7 @@ namespace etl //************************************************************************* void write_commit(const span& reserve) { - size_type windex = etl::distance(p_buffer, reserve.data()); + size_type windex = static_cast(etl::distance(p_buffer, reserve.data())); apply_write_reserve(windex, reserve.size()); } diff --git a/include/etl/chrono.h b/include/etl/chrono.h index facde8a4..b452ca4e 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -35,10 +35,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #if ETL_USING_CPP11 #include "hash.h" diff --git a/include/etl/closure.h b/include/etl/closure.h index 54b0fb36..7f11bbcf 100644 --- a/include/etl/closure.h +++ b/include/etl/closure.h @@ -33,53 +33,62 @@ SOFTWARE. #include "platform.h" #include "delegate.h" +#include "invoke.h" #include "tuple.h" #include "type_list.h" #include "utility.h" namespace etl { -#if ETL_USING_CPP11 && !defined(ETL_CLOSURE_FORCE_CPP03_IMPLEMENTATION) //************************************************************************* /// Base template for closure. + /// \tparam TSignature The callback signature. + /// \tparam TCallback The callback type, defaults to etl::delegate. //************************************************************************* - template + template > class closure; +#if ETL_USING_CPP11 && !defined(ETL_CLOSURE_FORCE_CPP03_IMPLEMENTATION) //************************************************************************* - /// Closure for binding arguments to a delegate and invoking it later. - /// Stores a delegate and its arguments, allowing deferred execution. + /// Closure for binding arguments to a callback and invoking it later. + /// Stores a callback and its arguments, allowing deferred execution. /// Arguments are stored in a tuple and can be rebound using bind(). /// Example usage: /// \code /// etl::closure c(my_delegate, 1, 2); /// c(); // Invokes my_delegate(1, 2) /// \endcode - /// \tparam TReturn The return type of the delegate. - /// \tparam TArgs The argument types of the delegate. + /// \tparam TReturn The return type of the callback. + /// \tparam TArgs The argument types of the callback. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - using delegate_type = etl::delegate; ///< The delegate type to be invoked. - using argument_types = etl::type_list; ///< The type list of arguments. + using delegate_type ETL_DEPRECATED_REASON("Use callback_type") = + TCallback; ///< The callback type to be invoked. Deprecated, use callback_type instead. + using callback_type = TCallback; ///< The callback type to be invoked. + using argument_types = etl::type_list; ///< The type list of arguments. + + static_assert(etl::is_invocable_r::value, "Callback is not invocable with the specified arguments"); + static_assert(etl::is_copy_constructible::value, "Callback type must be copy constructible"); //********************************************************************* - /// Construct a closure with a delegate and its arguments. - /// \param f The delegate to be invoked. - /// \param args The arguments to bind to the delegate. + /// Construct a closure with a callback and its arguments. + /// \param f The callback to be invoked. + /// \param args The arguments to bind to the callback. //********************************************************************* - ETL_CONSTEXPR14 closure(const delegate_type& f, const TArgs... args) + ETL_CONSTEXPR14 closure(const callback_type& f, const TArgs... args) : m_f(f) , m_args(args...) { } //********************************************************************* - /// Invoke the stored delegate with the bound arguments. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound arguments. + /// \return The result of the callback invocation. //********************************************************************* ETL_CONSTEXPR14 TReturn operator()() const { @@ -131,7 +140,7 @@ namespace etl //********************************************************************* /// Execute the closure with the stored arguments. /// \tparam idx Index sequence for tuple unpacking. - /// \return The result of the delegate invocation. + /// \return The result of the callback invocation. //********************************************************************* template ETL_CONSTEXPR14 TReturn execute(etl::index_sequence) const @@ -139,43 +148,38 @@ namespace etl return m_f(etl::get(m_args)...); } - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. etl::tuple m_args; ///< The bound arguments. }; #else //************************************************************************* - /// Base template for closure. - //************************************************************************* - template - class closure; - - //************************************************************************* - /// Closure for binding one argument to a delegate and invoking it later. - /// \tparam TReturn The return type of the delegate. + /// Closure for binding one argument to a callback and invoking it later. + /// \tparam TReturn The return type of the callback. /// \tparam TArg0 The type of the argument. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - /// The delegate type to be invoked. - typedef etl::delegate delegate_type; + /// The callback type to be invoked. + typedef TCallback callback_type; //********************************************************************* - /// Construct a closure with a delegate and its argument. - /// \param f The delegate to be invoked. - /// \param arg0 The argument to bind to the delegate. + /// Construct a closure with a callback and its argument. + /// \param f The callback to be invoked. + /// \param arg0 The argument to bind to the callback. //********************************************************************* - closure(const delegate_type& f, const TArg0 arg0) + closure(const callback_type& f, const TArg0 arg0) : m_f(f) , m_arg0(arg0) { } //********************************************************************* - /// Invoke the stored delegate with the bound argument. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound argument. + /// \return The result of the callback invocation. //********************************************************************* TReturn operator()() const { @@ -184,30 +188,31 @@ namespace etl private: - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. TArg0 m_arg0; }; //************************************************************************* - /// Closure for binding two arguments to a delegate and invoking it later. - /// \tparam TReturn The return type of the delegate. + /// Closure for binding two arguments to a callback and invoking it later. + /// \tparam TReturn The return type of the callback. /// \tparam TArg0 The type of the first argument. /// \tparam TArg1 The type of the second argument. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - typedef etl::delegate delegate_type; + typedef TCallback callback_type; //********************************************************************* - /// Construct a closure with a delegate and its arguments. - /// \param f The delegate to be invoked. + /// Construct a closure with a callback and its arguments. + /// \param f The callback to be invoked. /// \param arg0 The first argument to bind. /// \param arg1 The second argument to bind. //********************************************************************* - closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1) + closure(const callback_type& f, const TArg0 arg0, const TArg1 arg1) : m_f(f) , m_arg0(arg0) , m_arg1(arg1) @@ -215,8 +220,8 @@ namespace etl } //********************************************************************* - /// Invoke the stored delegate with the bound arguments. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound arguments. + /// \return The result of the callback invocation. //********************************************************************* TReturn operator()() const { @@ -225,33 +230,34 @@ namespace etl private: - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. TArg0 m_arg0; TArg1 m_arg1; }; //************************************************************************* - /// Closure for binding three arguments to a delegate and invoking it later. - /// \tparam TReturn The return type of the delegate. + /// Closure for binding three arguments to a callback and invoking it later. + /// \tparam TReturn The return type of the callback. /// \tparam TArg0 The type of the first argument. /// \tparam TArg1 The type of the second argument. /// \tparam TArg2 The type of the third argument. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - typedef etl::delegate delegate_type; + typedef TCallback callback_type; //********************************************************************* - /// Construct a closure with a delegate and its arguments. - /// \param f The delegate to be invoked. + /// Construct a closure with a callback and its arguments. + /// \param f The callback to be invoked. /// \param arg0 The first argument to bind. /// \param arg1 The second argument to bind. /// \param arg2 The third argument to bind. //********************************************************************* - closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2) + closure(const callback_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2) : m_f(f) , m_arg0(arg0) , m_arg1(arg1) @@ -260,8 +266,8 @@ namespace etl } //********************************************************************* - /// Invoke the stored delegate with the bound arguments. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound arguments. + /// \return The result of the callback invocation. //********************************************************************* TReturn operator()() const { @@ -270,36 +276,37 @@ namespace etl private: - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; }; //************************************************************************* - /// Closure for binding four arguments to a delegate and invoking it later. - /// \tparam TReturn The return type of the delegate. + /// Closure for binding four arguments to a callback and invoking it later. + /// \tparam TReturn The return type of the callback. /// \tparam TArg0 The type of the first argument. /// \tparam TArg1 The type of the second argument. /// \tparam TArg2 The type of the third argument. /// \tparam TArg3 The type of the fourth argument. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - typedef etl::delegate delegate_type; + typedef TCallback callback_type; //********************************************************************* - /// Construct a closure with a delegate and its arguments. - /// \param f The delegate to be invoked. + /// Construct a closure with a callback and its arguments. + /// \param f The callback to be invoked. /// \param arg0 The first argument to bind. /// \param arg1 The second argument to bind. /// \param arg2 The third argument to bind. /// \param arg3 The fourth argument to bind. //********************************************************************* - closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, const TArg3 arg3) + closure(const callback_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, const TArg3 arg3) : m_f(f) , m_arg0(arg0) , m_arg1(arg1) @@ -309,8 +316,8 @@ namespace etl } //********************************************************************* - /// Invoke the stored delegate with the bound arguments. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound arguments. + /// \return The result of the callback invocation. //********************************************************************* TReturn operator()() const { @@ -319,7 +326,7 @@ namespace etl private: - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; @@ -327,31 +334,32 @@ namespace etl }; //************************************************************************* - /// Closure for binding five arguments to a delegate and invoking it later. - /// \tparam TReturn The return type of the delegate. + /// Closure for binding five arguments to a callback and invoking it later. + /// \tparam TReturn The return type of the callback. /// \tparam TArg0 The type of the first argument. /// \tparam TArg1 The type of the second argument. /// \tparam TArg2 The type of the third argument. /// \tparam TArg3 The type of the fourth argument. /// \tparam TArg4 The type of the fifth argument. + /// \tparam TCallback The callback type. //************************************************************************* - template - class closure + template + class closure { public: - typedef etl::delegate delegate_type; + typedef TCallback callback_type; //********************************************************************* - /// Construct a closure with a delegate and its arguments. - /// \param f The delegate to be invoked. + /// Construct a closure with a callback and its arguments. + /// \param f The callback to be invoked. /// \param arg0 The first argument to bind. /// \param arg1 The second argument to bind. /// \param arg2 The third argument to bind. /// \param arg3 The fourth argument to bind. /// \param arg4 The fifth argument to bind. //********************************************************************* - closure(const delegate_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, const TArg3 arg3, const TArg4 arg4) + closure(const callback_type& f, const TArg0 arg0, const TArg1 arg1, const TArg2 arg2, const TArg3 arg3, const TArg4 arg4) : m_f(f) , m_arg0(arg0) , m_arg1(arg1) @@ -362,8 +370,8 @@ namespace etl } //********************************************************************* - /// Invoke the stored delegate with the bound arguments. - /// \return The result of the delegate invocation. + /// Invoke the stored callback with the bound arguments. + /// \return The result of the callback invocation. //********************************************************************* TReturn operator()() const { @@ -372,7 +380,7 @@ namespace etl private: - delegate_type m_f; ///< The delegate to invoke. + callback_type m_f; ///< The callback to invoke. TArg0 m_arg0; TArg1 m_arg1; TArg2 m_arg2; diff --git a/include/etl/concepts.h b/include/etl/concepts.h index ce5cec97..ac539947 100644 --- a/include/etl/concepts.h +++ b/include/etl/concepts.h @@ -36,10 +36,6 @@ SOFTWARE. #include "type_traits.h" #include "utility.h" -#if ETL_NOT_USING_CPP20 && !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR BELOW C++20 -#endif - #if ETL_USING_CPP20 #if ETL_USING_STL diff --git a/include/etl/const_map.h b/include/etl/const_map.h index aa20fb4d..f96f616b 100644 --- a/include/etl/const_map.h +++ b/include/etl/const_map.h @@ -33,10 +33,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #include "algorithm.h" #include "functional.h" #include "nth_type.h" @@ -45,6 +41,8 @@ SOFTWARE. #include "private/comparator_is_transparent.h" +#if ETL_USING_CPP11 + ///\defgroup const_map const_map ///\ingroup containers @@ -528,14 +526,14 @@ namespace etl value_type element_list[Size]; }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_map(TElements...) -> const_map::first_type, typename etl::nth_type_t<0, TElements...>::second_type, sizeof...(TElements)>; -#endif + #endif //********************************************************************* /// Map type designed for constexpr. @@ -586,16 +584,16 @@ namespace etl } }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_map_ext(const etl::span&) -> const_map_ext; template const_map_ext(const TElements (&)[Size]) -> const_map_ext; -#endif + #endif //************************************************************************* /// Equality test. @@ -659,3 +657,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/const_multimap.h b/include/etl/const_multimap.h index 6f5f8208..dea60ee1 100644 --- a/include/etl/const_multimap.h +++ b/include/etl/const_multimap.h @@ -33,10 +33,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #include "algorithm.h" #include "functional.h" #include "nth_type.h" @@ -45,6 +41,8 @@ SOFTWARE. #include "private/comparator_is_transparent.h" +#if ETL_USING_CPP11 + ///\defgroup const_multimap const_multimap ///\ingroup containers @@ -478,14 +476,14 @@ namespace etl value_type element_list[Size]; }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_multimap(TPairs...) -> const_multimap::first_type, typename etl::nth_type_t<0, TPairs...>::second_type, sizeof...(TPairs)>; -#endif + #endif //********************************************************************* /// Map type designed for constexpr. @@ -536,16 +534,16 @@ namespace etl } }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_multimap_ext(const etl::span&) -> const_multimap_ext; template const_multimap_ext(const TElements (&)[Size]) -> const_multimap_ext; -#endif + #endif //************************************************************************* /// Equality test. @@ -626,3 +624,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/const_multiset.h b/include/etl/const_multiset.h index 1fb0bd9e..6184f9e7 100644 --- a/include/etl/const_multiset.h +++ b/include/etl/const_multiset.h @@ -33,10 +33,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #include "algorithm.h" #include "functional.h" #include "nth_type.h" @@ -45,6 +41,8 @@ SOFTWARE. #include "private/comparator_is_transparent.h" +#if ETL_USING_CPP11 + ///\defgroup const_multiset const_multiset ///\ingroup containers @@ -433,13 +431,13 @@ namespace etl value_type element_list[Size]; }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_multiset(TElements...) -> const_multiset, sizeof...(TElements)>; -#endif + #endif //********************************************************************* /// Multiset type designed for constexpr. @@ -488,16 +486,16 @@ namespace etl } }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_multiset_ext(const etl::span&) -> const_multiset_ext; template const_multiset_ext(const TElements (&)[Size]) -> const_multiset_ext; -#endif + #endif //************************************************************************* /// Equality test. @@ -572,3 +570,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/const_set.h b/include/etl/const_set.h index e4629d71..df7f0989 100644 --- a/include/etl/const_set.h +++ b/include/etl/const_set.h @@ -33,10 +33,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #include "algorithm.h" #include "functional.h" #include "nth_type.h" @@ -45,6 +41,8 @@ SOFTWARE. #include "private/comparator_is_transparent.h" +#if ETL_USING_CPP11 + ///\defgroup const_set const_set ///\ingroup containers @@ -426,13 +424,13 @@ namespace etl value_type element_list[Size]; }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_set(TElements...) -> const_set, sizeof...(TElements)>; -#endif + #endif //********************************************************************* /// Map type designed for constexpr. @@ -481,16 +479,16 @@ namespace etl } }; - //************************************************************************* - /// Template deduction guides. - //************************************************************************* -#if ETL_USING_CPP17 + //************************************************************************* + /// Template deduction guides. + //************************************************************************* + #if ETL_USING_CPP17 template const_set_ext(const etl::span&) -> const_set_ext; template const_set_ext(const TElements (&)[Size]) -> const_set_ext; -#endif + #endif //************************************************************************* /// Equality test. @@ -548,3 +546,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/doxygen.h b/include/etl/doxygen.h index f9adce19..0251f1b6 100644 --- a/include/etl/doxygen.h +++ b/include/etl/doxygen.h @@ -27,31 +27,29 @@ SOFTWARE. ******************************************************************************/ ///\defgroup etl Embedded Template Library. -https - : // github.com/ETLCPP/etl - http - : // www.etlcpp.com +/// https://github.com/ETLCPP/etl +/// http://www.etlcpp.com - ///\defgroup containers Containers - ///\ingroup etl +///\defgroup containers Containers +///\ingroup etl - ///\defgroup utilities Utilities - /// A set of utility templates. - ///\ingroup etl +///\defgroup utilities Utilities +/// A set of utility templates. +///\ingroup etl - ///\defgroup maths Maths - /// A set of mathematical templates. - ///\ingroup etl +///\defgroup maths Maths +/// A set of mathematical templates. +///\ingroup etl - ///\defgroup patterns Patterns - /// A set of templated design patterns. - ///\ingroup etl +///\defgroup patterns Patterns +/// A set of templated design patterns. +///\ingroup etl - ///\defgroup crc CRC - /// A set of CRC calculations - ///\ingroup maths +///\defgroup crc CRC +/// A set of CRC calculations +///\ingroup maths - ///\ingroup etl - namespace etl +///\ingroup etl +namespace etl { } diff --git a/include/etl/format.h b/include/etl/format.h index 72c79be0..8ee8514e 100644 --- a/include/etl/format.h +++ b/include/etl/format.h @@ -1039,22 +1039,27 @@ namespace etl { const size_t fractional_decimals = 6; // default - T integral; - T fractional = modf(value, &integral); - bool sign; - unsigned long long int fractional_int; - unsigned long long int integral_int; - if (integral < 0.0) + // Detect sign using signbit to correctly handle -0.0 + bool sign = signbit(value); + + T integral; + T fractional = modf(value, &integral); + + // Take absolute values to avoid casting negative values to unsigned + if (sign) { - sign = true; - fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); - integral_int = static_cast(-integral); + fractional = -fractional; + integral = -integral; } - else + + unsigned long long int scale = int_pow(10, fractional_decimals); + unsigned long long int fractional_int = static_cast(round(fractional * scale)); + unsigned long long int integral_int = static_cast(integral); + + if (fractional_int == scale) { - sign = false; - fractional_int = static_cast(fractional * pow(10., fractional_decimals)); - integral_int = static_cast(integral); + fractional_int = 0; + ++integral_int; } private_format::format_sign(it, sign ? -1 : 0, spec); @@ -1071,9 +1076,8 @@ namespace etl static const size_t exponent_decimals = 1; long long int exponent_int = 0; - bool sign; - unsigned long long int fractional_int; - unsigned long long int integral_int; + // Detect sign using signbit to correctly handle -0.0 + bool sign = signbit(value); T integral; T fractional = modf(value, &integral); @@ -1092,17 +1096,21 @@ namespace etl fractional = modf(value, &integral); } - if (integral < 0.0) + // Take absolute values to avoid casting negative values to unsigned + if (sign) { - sign = true; - fractional_int = static_cast(-fractional * pow(static_cast(0x10), fractional_decimals)); - integral_int = static_cast(-integral); + fractional = -fractional; + integral = -integral; } - else + + unsigned long long int scale = int_pow(0x10, fractional_decimals); + unsigned long long int fractional_int = static_cast(round(fractional * scale)); + unsigned long long int integral_int = static_cast(integral); + + if (fractional_int == scale) { - sign = false; - fractional_int = static_cast(fractional * pow(static_cast(0x10), fractional_decimals)); - integral_int = static_cast(integral); + fractional_int = 0; + ++integral_int; } private_format::format_sign(it, sign ? -1 : 0, spec); @@ -1133,9 +1141,8 @@ namespace etl static const size_t exponent_decimals = 2; long long int exponent_int = 0; - bool sign; - unsigned long long int fractional_int; - unsigned long long int integral_int; + // Detect sign using signbit to correctly handle -0.0 + bool sign = std::signbit(value); T integral; T fractional = modf(value, &integral); @@ -1154,17 +1161,21 @@ namespace etl fractional = modf(value, &integral); } - if (integral < 0.0) + // Take absolute values to avoid casting negative values to unsigned + if (sign) { - sign = true; - fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); - integral_int = static_cast(-integral); + fractional = -fractional; + integral = -integral; } - else + + unsigned long long int scale = int_pow(10, fractional_decimals); + unsigned long long int fractional_int = static_cast(round(fractional * scale)); + unsigned long long int integral_int = static_cast(integral); + + if (fractional_int == scale) { - sign = false; - fractional_int = static_cast(fractional * pow(10., fractional_decimals)); - integral_int = static_cast(integral); + fractional_int = 0; + ++integral_int; } private_format::format_sign(it, sign ? -1 : 0, spec); @@ -1186,22 +1197,27 @@ namespace etl { const size_t fractional_decimals = 6; // default - T integral; - T fractional = modf(value, &integral); - bool sign; - unsigned long long int fractional_int; - unsigned long long int integral_int; - if (integral < 0.0) + // Detect sign using signbit to correctly handle -0.0 + bool sign = std::signbit(value); + + T integral; + T fractional = modf(value, &integral); + + // Take absolute values to avoid casting negative values to unsigned + if (sign) { - sign = true; - fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); - integral_int = static_cast(-integral); + fractional = -fractional; + integral = -integral; } - else + + unsigned long long int scale = int_pow(10, fractional_decimals); + unsigned long long int fractional_int = static_cast(round(fractional * scale)); + unsigned long long int integral_int = static_cast(integral); + + if (fractional_int == scale) { - sign = false; - fractional_int = static_cast(fractional * pow(10., fractional_decimals)); - integral_int = static_cast(integral); + fractional_int = 0; + ++integral_int; } private_format::format_sign(it, sign ? -1 : 0, spec); diff --git a/include/etl/ipool.h b/include/etl/ipool.h index c71254bf..e53c4014 100644 --- a/include/etl/ipool.h +++ b/include/etl/ipool.h @@ -644,7 +644,7 @@ namespace etl // in debug. #if ETL_IS_DEBUG_BUILD // Is the address on a valid object boundary? - bool is_valid_address = ((distance % Item_Size) == 0); + bool is_valid_address = ((static_cast(distance) % Item_Size) == 0); #else bool is_valid_address = true; #endif diff --git a/include/etl/iterator.h b/include/etl/iterator.h index 8a09e7c0..263ab5c6 100644 --- a/include/etl/iterator.h +++ b/include/etl/iterator.h @@ -958,13 +958,121 @@ namespace etl template ETL_CONSTANT bool is_random_access_iterator_concept::value; +#if ETL_USING_CPP11 + //*************************************************************************** + /// Trait to detect if a type is a container (has iterator and begin/end) + /// but is not itself an iterator. + /// Used to constrain begin()/end() free functions in C++26. + //*************************************************************************** + namespace private_iterator + { + // Check if T has iterator_category (i.e., is an iterator) + template + struct has_iterator_category : etl::false_type + { + }; + + template + struct has_iterator_category> : etl::true_type + { + }; + + // is_container: has iterator/const_iterator/begin/end but does NOT have iterator_category + template + struct is_container : etl::false_type + { + }; + + template + struct is_container< + T, etl::void_t< typename T::iterator, typename T::const_iterator, decltype(etl::declval().begin()), decltype(etl::declval().end()) >> + : etl::bool_constant::value> + { + }; + } // namespace private_iterator +#endif + #if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + #if ETL_USING_CPP11 + + //***************************************************************************** + /// Get the 'begin' iterator. + /// Note: Contains SFINAE guard, ensuring they only participate in overload + /// resolution when TContainer actually has the corresponding member function. + /// This prevents ADL from matching these templates when std::ranges::begin + /// performs an unqualified call on etl:: iterator types. + ///\ingroup container + //***************************************************************************** + template ().begin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::iterator>::type + begin(TContainer& container) + { + return container.begin(); + } + + //***************************************************************************** + /// Get the 'begin' const_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().begin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_iterator>::type + begin(const TContainer& container) + { + return container.begin(); + } + + //***************************************************************************** + /// Get the 'begin' const_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().cbegin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_iterator>::type + cbegin(const TContainer& container) + { + return container.cbegin(); + } + + //***************************************************************************** + /// Get the 'end' iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().end())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::iterator>::type end(TContainer& container) + { + return container.end(); + } + + //***************************************************************************** + /// Get the 'end' const_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().end())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_iterator>::type + end(const TContainer& container) + { + return container.end(); + } + + //***************************************************************************** + /// Get the 'end' const_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().cend())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_iterator>::type + cend(const TContainer& container) + { + return container.cend(); + } + #else + // C++03 fallback: + // - no SFINAE guards needed since std::ranges does not exist + // - no constraint needed as C++26 ADL issue doesn't apply //***************************************************************************** /// Get the 'begin' iterator. ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::iterator begin(TContainer& container) + typename TContainer::iterator begin(TContainer& container) { return container.begin(); } @@ -974,7 +1082,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_iterator begin(const TContainer& container) + typename TContainer::const_iterator begin(const TContainer& container) { return container.begin(); } @@ -984,7 +1092,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_iterator cbegin(const TContainer& container) + typename TContainer::const_iterator cbegin(const TContainer& container) { return container.cbegin(); } @@ -994,7 +1102,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::iterator end(TContainer& container) + typename TContainer::iterator end(TContainer& container) { return container.end(); } @@ -1004,7 +1112,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_iterator end(const TContainer& container) + typename TContainer::const_iterator end(const TContainer& container) { return container.end(); } @@ -1014,10 +1122,11 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_iterator cend(const TContainer& container) + typename TContainer::const_iterator cend(const TContainer& container) { return container.cend(); } + #endif //***************************************************************************** /// Get the 'begin' pointer for an array. @@ -1081,12 +1190,83 @@ namespace etl #endif #if ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED + #if ETL_USING_CPP11 + //***************************************************************************** + /// Get the 'begin' reverse_iterator for a container. + /// Note: Contains SFINAE guard (see begin/end above for rationale). + ///\ingroup container + //***************************************************************************** + template ().rbegin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::reverse_iterator>::type + rbegin(TContainer& container) + { + return container.rbegin(); + } + + //***************************************************************************** + /// Get the 'begin' reverse_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().rbegin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_reverse_iterator>::type + rbegin(const TContainer& container) + { + return container.rbegin(); + } + + //***************************************************************************** + /// Get the 'begin' reverse_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().crbegin())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_reverse_iterator>::type + crbegin(const TContainer& container) + { + return container.crbegin(); + } + + //***************************************************************************** + /// Get the 'end' reverse_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().rend())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::reverse_iterator>::type + rend(TContainer& container) + { + return container.rend(); + } + + //***************************************************************************** + /// Get the 'end' reverse_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().rend())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_reverse_iterator>::type + rend(const TContainer& container) + { + return container.rend(); + } + + //***************************************************************************** + /// Get the 'end' reverse_iterator for a container. + ///\ingroup container + //***************************************************************************** + template ().crend())> > + ETL_CONSTEXPR typename etl::enable_if::value, typename TContainer::const_reverse_iterator>::type + crend(const TContainer& container) + { + return container.crend(); + } + #else + // C++03 fallback: + // - no SFINAE guards needed since std::ranges does not exist. + // - no constraint needed as C++26 ADL issue doesn't apply //***************************************************************************** /// Get the 'begin' reverse_iterator for a container. ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::reverse_iterator rbegin(TContainer& container) + typename TContainer::reverse_iterator rbegin(TContainer& container) { return container.rbegin(); } @@ -1096,7 +1276,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_reverse_iterator rbegin(const TContainer& container) + typename TContainer::const_reverse_iterator rbegin(const TContainer& container) { return container.rbegin(); } @@ -1106,7 +1286,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_reverse_iterator crbegin(const TContainer& container) + typename TContainer::const_reverse_iterator crbegin(const TContainer& container) { return container.crbegin(); } @@ -1116,7 +1296,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::reverse_iterator rend(TContainer& container) + typename TContainer::reverse_iterator rend(TContainer& container) { return container.rend(); } @@ -1126,7 +1306,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_reverse_iterator rend(const TContainer& container) + typename TContainer::const_reverse_iterator rend(const TContainer& container) { return container.rend(); } @@ -1136,10 +1316,11 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR typename TContainer::const_reverse_iterator crend(const TContainer& container) + typename TContainer::const_reverse_iterator crend(const TContainer& container) { return container.crend(); } + #endif //***************************************************************************** /// Get the 'begin' reverse_iterator for an array. diff --git a/include/etl/manchester.h b/include/etl/manchester.h index 032d9e29..b385565d 100644 --- a/include/etl/manchester.h +++ b/include/etl/manchester.h @@ -35,6 +35,8 @@ SOFTWARE. #include "span.h" #include "static_assert.h" +#if ETL_USING_CPP11 + ///\defgroup manchester manchester /// Manchester encoding and decoding ///\ingroup utilities @@ -51,13 +53,13 @@ namespace etl struct is_encodable { static const bool value = -#if ETL_USING_8BIT_TYPES + #if ETL_USING_8BIT_TYPES etl::is_same::value || -#endif + #endif etl::is_same::value -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES || etl::is_same::value -#endif + #endif ; }; @@ -69,13 +71,13 @@ namespace etl struct is_decodable { static const bool value = -#if ETL_USING_8BIT_TYPES + #if ETL_USING_8BIT_TYPES etl::is_same::value || -#endif + #endif etl::is_same::value -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES || etl::is_same::value -#endif + #endif ; }; @@ -91,13 +93,13 @@ namespace etl ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester encoding type should be one of [uint8_t, uint16_t, uint32_t]"); }; -#if ETL_USING_8BIT_TYPES + #if ETL_USING_8BIT_TYPES template <> struct encoded { typedef uint16_t type; }; -#endif + #endif template <> struct encoded @@ -105,13 +107,13 @@ namespace etl typedef uint32_t type; }; -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES template <> struct encoded { typedef uint64_t type; }; -#endif + #endif //************************************************************************* /// Type trait to determine the decoded type for a given encoded type. @@ -125,13 +127,13 @@ namespace etl ETL_STATIC_ASSERT(sizeof(T) == 0, "Manchester decoding type should be one of [uint16_t, uint32_t, uint64_t]"); }; -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES template <> struct decoded { typedef uint8_t type; }; -#endif + #endif template <> struct decoded @@ -139,24 +141,24 @@ namespace etl typedef uint16_t type; }; -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES template <> struct decoded { typedef uint32_t type; }; -#endif + #endif //************************************************************************* /// Normal Manchester encoding type (no inversion). //************************************************************************* struct manchester_type_normal { -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES static const uint64_t inversion_mask = 0x0000000000000000ULL; -#else + #else static const uint32_t inversion_mask = 0x00000000UL; -#endif + #endif }; //************************************************************************* @@ -164,11 +166,11 @@ namespace etl //************************************************************************* struct manchester_type_inverted { -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES static const uint64_t inversion_mask = 0xFFFFFFFFFFFFFFFFULL; -#else + #else static const uint32_t inversion_mask = 0xFFFFFFFFUL; -#endif + #endif }; //************************************************************************* @@ -247,11 +249,11 @@ namespace etl ETL_STATIC_ASSERT(CHAR_BIT == etl::numeric_limits::digits, "Manchester requires uint_least8_t to have the same number of bits as CHAR (CHAR_BITS)"); - //************************************************************************* - // Encoding functions - //************************************************************************* + //************************************************************************* + // Encoding functions + //************************************************************************* -#if ETL_USING_8BIT_TYPES + #if ETL_USING_8BIT_TYPES //************************************************************************* /// Encode a 8-bit unsigned value and return 16-bit result. ///\param decoded The value to encode. @@ -273,7 +275,7 @@ namespace etl ^ (0xAAAAU ^ static_cast(TManchesterType::inversion_mask))); return encoded; } -#endif + #endif //************************************************************************* /// Encode a 16-bit unsigned value and return the 32-bit result. @@ -297,7 +299,7 @@ namespace etl return encoded; } -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES //************************************************************************* /// Encode a 32-bit unsigned value and return the 64-bit result. ///\param decoded The value to encode. @@ -320,7 +322,7 @@ namespace etl encoded = (encoded | (encoded << 1U)) ^ (0xAAAAAAAAAAAAAAAAULL ^ TManchesterType::inversion_mask); return encoded; } -#endif + #endif //************************************************************************* /// Encode a span of data with the specified chunk size. @@ -350,11 +352,11 @@ namespace etl } } - //************************************************************************* - // Decoding functions - //************************************************************************* + //************************************************************************* + // Decoding functions + //************************************************************************* -#if ETL_USING_8BIT_TYPES + #if ETL_USING_8BIT_TYPES //************************************************************************* /// Decode a 16-bit value and return the 8-bit result. ///\param encoded The value to decode. @@ -373,7 +375,7 @@ namespace etl encoded = static_cast((static_cast(encoded) | (static_cast(encoded) >> 2)) & 0x0F0FU); return static_cast(static_cast(encoded) | (static_cast(encoded) >> 4U)); } -#endif + #endif //************************************************************************* /// Decode a 32-bit value and return the 16-bit result. @@ -394,7 +396,7 @@ namespace etl return static_cast(encoded | (encoded >> 8U)); } -#if ETL_USING_64BIT_TYPES + #if ETL_USING_64BIT_TYPES //************************************************************************* /// Decode a 64-bit value and return the 32-bit result. ///\param encoded The value to decode. @@ -414,7 +416,7 @@ namespace etl encoded = (encoded | (encoded >> 8)) & 0x0000FFFF0000FFFFULL; return static_cast(encoded | (encoded >> 16U)); } -#endif + #endif //************************************************************************* /// Decode a span of data using the specified chunk type. @@ -500,3 +502,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/memory.h b/include/etl/memory.h index b1456298..0bf9e3d6 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -1798,6 +1798,117 @@ namespace etl } // namespace ranges #endif +#if ETL_USING_CPP11 + //***************************************************************************** + /// Trivially relocate a range of objects. + /// This function relocates objects by copying their bytes using memmove. + /// The source objects' lifetimes are ended without calling destructors. + /// Based on C++26 P2786R13. + /// https://en.cppreference.com/w/cpp/memory/trivially_relocate + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value && !etl::is_const::value, T*>::type trivially_relocate(T* first, T* last, + T* result) + { + if (first == result) + { + return last; + } + + const size_t count = static_cast(last - first); + + if (count > 0) + { + // Use memmove to handle overlapping ranges + ::memmove(static_cast(result), static_cast(first), count * sizeof(T)); + } + + return result + count; + } + + //***************************************************************************** + /// Relocate implementation for trivially relocatable types. + /// Delegates to etl::trivially_relocate. + /// Uses SFINAE (enable_if) so that etl::trivially_relocate is never + /// instantiated for non-trivially relocatable types on pre-C++17 compilers, + /// avoiding the ill-formed instantiation that would occur with a plain + /// ETL_IF_CONSTEXPR branch. + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value, T*>::type relocate_impl(T* first, T* last, T* result) + { + return etl::trivially_relocate(first, last, result); + } + + //***************************************************************************** + /// Relocate implementation for non-trivially relocatable types. + /// Uses move construction + destroy. + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value, T*>::type relocate_impl(T* first, T* last, T* result) + { + const ptrdiff_t count = last - first; + + // Check if ranges overlap and handle accordingly + if (result < first || result >= last) + { + // No overlap or destination is after source - iterate forward + T* src = first; + T* dst = result; + while (src != last) + { + ::new (static_cast(dst)) T(etl::move(*src)); + src->~T(); + ++src; + ++dst; + } + } + else + { + // Destination overlaps with source from below - iterate backward + T* src = last; + T* dst = result + count; + while (src != first) + { + --src; + --dst; + ::new (static_cast(dst)) T(etl::move(*src)); + src->~T(); + } + } + + return result + count; + } + + //***************************************************************************** + /// Relocate a range of objects. + /// For trivially relocatable types, uses trivially_relocate via relocate_impl. + /// For other nothrow relocatable types, uses move + destroy via relocate_impl. + /// Delegates to SFINAE-guarded relocate_impl overloads instead of using + /// ETL_IF_CONSTEXPR, so that etl::trivially_relocate is never instantiated + /// for non-trivially relocatable types on pre-C++17 compilers. + /// Based on C++26 P2786R13. + /// https://en.cppreference.com/w/cpp/memory/relocate + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value && !etl::is_const::value, T*>::type relocate(T* first, T* last, T* result) + { + // Handle trivial relocation case + if (first == result || first == last) + { + return (first == result) ? last : result; + } + + // SFINAE on etl::is_trivially_relocatable selects the correct overload + // so that etl::trivially_relocate is only instantiated when valid. + return relocate_impl(first, last, result); + } +#endif + //***************************************************************************** /// Default deleter. ///\tparam T The pointed to type type. diff --git a/include/etl/numeric.h b/include/etl/numeric.h index 633755e5..7e740839 100644 --- a/include/etl/numeric.h +++ b/include/etl/numeric.h @@ -130,11 +130,11 @@ namespace etl { if (a > b) { - return b + (etl::distance(b, a) / 2U); + return b + (etl::distance(b, a) / 2); } else { - return a + (etl::distance(a, b) / 2U); + return a + (etl::distance(a, b) / 2); } } @@ -151,11 +151,11 @@ namespace etl { if (a > b) { - return b + (etl::distance(b, a) / 2U); + return b + (etl::distance(b, a) / 2); } else { - return a + (etl::distance(a, b) / 2U); + return a + (etl::distance(a, b) / 2); } } @@ -172,7 +172,7 @@ namespace etl || etl::is_same::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value)), int>::type = 0) { - etl::advance(a, etl::distance(a, b) / 2U); + etl::advance(a, etl::distance(a, b) / 2); return a; } @@ -204,6 +204,284 @@ namespace etl return typecast_a(a) + (typecast_t(t) * (typecast_b(b) - typecast_a(a))); } + + //*************************************************************************** + /// Saturating addition for unsigned integers. + /// Returns x + y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type add_sat(T x, T y) ETL_NOEXCEPT + { + T result = static_cast(x + y); + // Overflow occurred if result < x + if (result < x) + { + return etl::numeric_limits::max(); + } + return result; + } + + //*************************************************************************** + /// Saturating addition for signed integers. + /// Returns x + y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type add_sat(T x, T y) ETL_NOEXCEPT + { + // Check for overflow: both operands have same sign and result has different sign + if (y > T(0)) + { + // Positive overflow check + if (x > (etl::numeric_limits::max() - y)) + { + return etl::numeric_limits::max(); + } + } + else + { + // Negative overflow check + if (x < (etl::numeric_limits::min() - y)) + { + return etl::numeric_limits::min(); + } + } + + return static_cast(x + y); + } + + //*************************************************************************** + /// Saturating subtraction for unsigned integers. + /// Returns x - y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type sub_sat(T x, T y) ETL_NOEXCEPT + { + // Underflow occurred if y > x + if (y > x) + { + return T(0); + } + return static_cast(x - y); + } + + //*************************************************************************** + /// Saturating subtraction for signed integers. + /// Returns x - y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type sub_sat(T x, T y) ETL_NOEXCEPT + { + // Check for overflow/underflow + if (y > T(0)) + { + // Subtracting positive: check for underflow + if (x < (etl::numeric_limits::min() + y)) + { + return etl::numeric_limits::min(); + } + } + else + { + // Subtracting negative (adding): check for overflow + if (x > (etl::numeric_limits::max() + y)) + { + return etl::numeric_limits::max(); + } + } + + return static_cast(x - y); + } + + //*************************************************************************** + /// Saturating multiplication for unsigned integers. + /// Returns x * y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type mul_sat(T x, T y) ETL_NOEXCEPT + { + if ((x == T(0)) || (y == T(0))) + { + return T(0); + } + + // Check for overflow: x * y > max => x > max / y + if (x > (etl::numeric_limits::max() / y)) + { + return etl::numeric_limits::max(); + } + + return static_cast(x * y); + } + + //*************************************************************************** + /// Saturating multiplication for signed integers. + /// Returns x * y, clamped to the range of T. + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type mul_sat(T x, T y) ETL_NOEXCEPT + { + if ((x == T(0)) || (y == T(0))) + { + return T(0); + } + + // Both positive + if ((x > T(0)) && (y > T(0))) + { + if (x > (etl::numeric_limits::max() / y)) + { + return etl::numeric_limits::max(); + } + } + // Both negative + else if ((x < T(0)) && (y < T(0))) + { + if (x < (etl::numeric_limits::max() / y)) + { + return etl::numeric_limits::max(); + } + } + // Different signs (x positive, y negative) + else if ((x > T(0)) && (y < T(0))) + { + if (y < (etl::numeric_limits::min() / x)) + { + return etl::numeric_limits::min(); + } + } + // Different signs (x negative, y positive) + else + { + if (x < (etl::numeric_limits::min() / y)) + { + return etl::numeric_limits::min(); + } + } + + return static_cast(x * y); + } + + //*************************************************************************** + /// Saturating division for unsigned integers. + /// Returns x / y. For unsigned types, no saturation is needed. + /// \pre y != 0 (undefined behaviour if y is zero, matching C++26). + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type div_sat(T x, T y) ETL_NOEXCEPT + { + return static_cast(x / y); + } + + //*************************************************************************** + /// Saturating division for signed integers. + /// Returns x / y, clamped to the range of T. + /// The only case of overflow is min / -1. + /// \pre y != 0 (undefined behaviour if y is zero, matching C++26). + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type div_sat(T x, T y) ETL_NOEXCEPT + { + // The only overflow case: min / -1 would be max + 1 + if ((x == etl::numeric_limits::min()) && (y == T(-1))) + { + return etl::numeric_limits::max(); + } + + return static_cast(x / y); + } + + //*************************************************************************** + /// saturate_cast + /// Converts an integer value to another integer type, clamping the value + /// to the representable range of the destination type. + /// C++26 equivalent of std::saturate_cast. + /// + /// When the source value is within the range of R, returns the value as R. + /// When the source value is below R's minimum, returns numeric_limits::min(). + /// When the source value is above R's maximum, returns numeric_limits::max(). + //*************************************************************************** + + // Case 1: Both unsigned. + template + ETL_CONSTEXPR14 + typename etl::enable_if::value && etl::is_integral::value && etl::is_unsigned::value && etl::is_unsigned::value, + R>::type + saturate_cast(T value) ETL_NOEXCEPT + { + // If sizeof(R) >= sizeof(T), all values of T fit in R. + // If sizeof(R) < sizeof(T), clamp to R's max. The comparison is safe + // because R's max fits in T when T is wider. + if ((sizeof(R) < sizeof(T)) && (value > static_cast(etl::numeric_limits::max()))) + { + return etl::numeric_limits::max(); + } + return static_cast(value); + } + + // Case 2: Both signed. + template + ETL_CONSTEXPR14 + typename etl::enable_if::value && etl::is_integral::value && etl::is_signed::value && etl::is_signed::value, R>::type + saturate_cast(T value) ETL_NOEXCEPT + { + // Only need to clamp when narrowing (R is smaller than T). + // When sizeof(R) >= sizeof(T), all values of T fit in R. + if (sizeof(R) < sizeof(T)) + { + if (value > static_cast(etl::numeric_limits::max())) + { + return etl::numeric_limits::max(); + } + if (value < static_cast(etl::numeric_limits::min())) + { + return etl::numeric_limits::min(); + } + } + return static_cast(value); + } + + // Case 3: Signed source -> Unsigned destination. + template + ETL_CONSTEXPR14 + typename etl::enable_if::value && etl::is_integral::value && etl::is_unsigned::value && etl::is_signed::value, + R>::type + saturate_cast(T value) ETL_NOEXCEPT + { + if (value < T(0)) + { + return R(0); + } + + typedef typename etl::make_unsigned::type unsigned_t; + unsigned_t uvalue = static_cast(value); + + // Compare in unsigned domain. R's max is always representable as unsigned_t + // when sizeof(T) > sizeof(R), and when sizeof(R) >= sizeof(T) all positive + // values of T fit in R. + if ((sizeof(R) < sizeof(T)) && (uvalue > static_cast(etl::numeric_limits::max()))) + { + return etl::numeric_limits::max(); + } + return static_cast(value); + } + + // Case 4: Unsigned source -> Signed destination. + template + ETL_CONSTEXPR14 + typename etl::enable_if::value && etl::is_integral::value && etl::is_signed::value && etl::is_unsigned::value, + R>::type + saturate_cast(T value) ETL_NOEXCEPT + { + // R's max is positive, so we can safely represent it as T (unsigned) when + // sizeof(T) >= sizeof(R). When sizeof(T) < sizeof(R), all values of T fit. + typedef typename etl::make_unsigned::type unsigned_r; + + if (value > static_cast(static_cast(etl::numeric_limits::max()))) + { + return etl::numeric_limits::max(); + } + return static_cast(value); + } } // namespace etl #endif diff --git a/include/etl/optional.h b/include/etl/optional.h index fc0db4f7..c7958dfb 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -127,7 +127,7 @@ namespace etl /// Constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl() + optional_impl() ETL_NOEXCEPT : storage() { } @@ -136,7 +136,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(etl::nullopt_t) + optional_impl(etl::nullopt_t) ETL_NOEXCEPT : storage() { } @@ -146,7 +146,7 @@ namespace etl /// Copy constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(const optional_impl& other) + optional_impl(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { if (other.has_value()) { @@ -160,7 +160,7 @@ namespace etl /// Move constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(optional_impl&& other) + optional_impl(optional_impl&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { if (other.has_value()) { @@ -177,7 +177,7 @@ namespace etl typename etl::enable_if< etl::is_constructible::value && !etl::is_same::type, etl::in_place_t>::value && !etl::is_same::type, optional_impl>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional_impl(U&& value_) + ETL_CONSTEXPR20_STL optional_impl(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(value_)); } @@ -186,7 +186,7 @@ namespace etl /// Constructor from variadic args. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, TArgs&&... args) + ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(args)...); } @@ -197,6 +197,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { storage.construct(ilist, etl::forward(args)...); } @@ -207,7 +208,7 @@ namespace etl /// Destructor. //*************************************************************************** ETL_CONSTEXPR20_STL - ~optional_impl() + ~optional_impl() ETL_NOEXCEPT { storage.destroy(); } @@ -216,7 +217,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(etl::nullopt_t) + optional_impl& operator=(etl::nullopt_t) ETL_NOEXCEPT { if (has_value()) { @@ -230,7 +231,7 @@ namespace etl /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(const optional_impl& other) + optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { if (this != &other) { @@ -252,7 +253,7 @@ namespace etl /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(optional_impl&& other) + optional_impl& operator=(optional_impl&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { if (this != &other) { @@ -277,7 +278,7 @@ namespace etl template ::value && !etl::is_same::type, optional_impl>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional_impl& operator=(U&& value_) + ETL_CONSTEXPR20_STL optional_impl& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(value_)); @@ -488,7 +489,7 @@ namespace etl /// Reset back to invalid. //*************************************************************************** ETL_CONSTEXPR20_STL - void reset() + void reset() ETL_NOEXCEPT { storage.destroy(); } @@ -518,7 +519,7 @@ namespace etl template < typename U, typename... URest, typename etl::enable_if< !etl::is_base_of< optional_impl, typename etl::remove_cv< typename etl::remove_reference::type>::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL T& emplace(U&& first, URest&&... rest) + ETL_CONSTEXPR20_STL T& emplace(U&& first, URest&&... rest) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(first), etl::forward(rest)...); @@ -529,7 +530,7 @@ namespace etl /// Emplaces with zero arguments, i.e. default construct emplace. //************************************************************************* ETL_CONSTEXPR20_STL - T& emplace() + T& emplace() ETL_NOEXCEPT_IF(etl::is_nothrow_default_constructible::value) { storage.construct(); @@ -735,7 +736,7 @@ namespace etl //*************************************************************************** /// Constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl() + ETL_CONSTEXPR14 optional_impl() ETL_NOEXCEPT : storage() { } @@ -743,7 +744,7 @@ namespace etl //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(etl::nullopt_t) + ETL_CONSTEXPR14 optional_impl(etl::nullopt_t) ETL_NOEXCEPT : storage() { } @@ -752,7 +753,7 @@ namespace etl //*************************************************************************** /// Copy constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(const optional_impl& other) + ETL_CONSTEXPR14 optional_impl(const optional_impl& other) ETL_NOEXCEPT { if (other.has_value()) { @@ -765,7 +766,7 @@ namespace etl //*************************************************************************** /// Move constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(optional_impl&& other) + ETL_CONSTEXPR14 optional_impl(optional_impl&& other) ETL_NOEXCEPT { if (other.has_value()) { @@ -776,7 +777,7 @@ namespace etl //*************************************************************************** /// Constructor from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(const T& value_) + ETL_CONSTEXPR14 optional_impl(const T& value_) ETL_NOEXCEPT { storage.construct(value_); } @@ -784,7 +785,7 @@ namespace etl //*************************************************************************** /// Constructor from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(T&& value_) + ETL_CONSTEXPR14 optional_impl(T&& value_) ETL_NOEXCEPT { storage.construct(etl::move(value_)); } @@ -793,7 +794,7 @@ namespace etl /// Constructor from variadic args. //*************************************************************************** template - ETL_CONSTEXPR14 optional_impl(etl::in_place_t, TArgs&&... args) + ETL_CONSTEXPR14 optional_impl(etl::in_place_t, TArgs&&... args) ETL_NOEXCEPT { storage.construct(etl::forward(args)...); } @@ -803,7 +804,7 @@ namespace etl /// Construct from initializer_list and arguments. //******************************************* template - ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) ETL_NOEXCEPT { storage.construct(ilist, etl::forward(args)...); } @@ -813,7 +814,7 @@ namespace etl //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(etl::nullopt_t) + ETL_CONSTEXPR14 optional_impl& operator=(etl::nullopt_t) ETL_NOEXCEPT { if (has_value()) { @@ -826,7 +827,7 @@ namespace etl //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl& other) + ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT { if (this != &other) { @@ -847,7 +848,7 @@ namespace etl //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(optional_impl&& other) + ETL_CONSTEXPR14 optional_impl& operator=(optional_impl&& other) ETL_NOEXCEPT { if (this != &other) { @@ -868,7 +869,7 @@ namespace etl //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(const T& value_) + ETL_CONSTEXPR14 optional_impl& operator=(const T& value_) ETL_NOEXCEPT { storage.construct(value_); @@ -879,7 +880,7 @@ namespace etl //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(T&& value_) + ETL_CONSTEXPR14 optional_impl& operator=(T&& value_) ETL_NOEXCEPT { storage.construct(etl::move(value_)); @@ -1058,7 +1059,7 @@ namespace etl //*************************************************************************** /// Swaps this value with another. //*************************************************************************** - ETL_CONSTEXPR14 void swap(optional_impl& other) + ETL_CONSTEXPR14 void swap(optional_impl& other) ETL_NOEXCEPT { optional_impl temp(*this); *this = other; @@ -1068,7 +1069,7 @@ namespace etl //*************************************************************************** /// Reset back to invalid. //*************************************************************************** - ETL_CONSTEXPR14 void reset() + ETL_CONSTEXPR14 void reset() ETL_NOEXCEPT { storage.destroy(); } @@ -1094,7 +1095,7 @@ namespace etl ///\param args The arguments to construct with. //************************************************************************* template - ETL_CONSTEXPR14 T& emplace(TArgs&&... args) + ETL_CONSTEXPR14 T& emplace(TArgs&&... args) ETL_NOEXCEPT { storage.construct(etl::forward(args)...); @@ -1286,7 +1287,7 @@ namespace etl /// Constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional() + ETL_CONSTEXPR14 optional() ETL_NOEXCEPT : impl_t() { } @@ -1295,12 +1296,12 @@ namespace etl /// Constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional() + ETL_CONSTEXPR20_STL optional() ETL_NOEXCEPT : impl_t() { } #else - optional() + optional() ETL_NOEXCEPT : impl_t() { } @@ -1311,7 +1312,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** template - ETL_CONSTEXPR14 optional(etl::nullopt_t) + ETL_CONSTEXPR14 optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1320,7 +1321,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(etl::nullopt_t) + ETL_CONSTEXPR20_STL optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1328,7 +1329,7 @@ namespace etl //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** - optional(etl::nullopt_t) + optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1340,7 +1341,7 @@ namespace etl /// Copy constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional(const optional& other) + ETL_CONSTEXPR14 optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) : impl_t(other) { } @@ -1349,7 +1350,7 @@ namespace etl /// Copy constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(const optional& other) + ETL_CONSTEXPR20_STL optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) : impl_t(other) { } @@ -1369,8 +1370,8 @@ namespace etl /// Move constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional(optional&& other) - : impl_t(other) + ETL_CONSTEXPR14 optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) + : impl_t(etl::move(other)) { } @@ -1378,8 +1379,8 @@ namespace etl /// Move constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(optional&& other) - : impl_t(other) + ETL_CONSTEXPR20_STL optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) + : impl_t(etl::move(other)) { } #endif @@ -1396,7 +1397,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR14 optional(U&& value_) + ETL_CONSTEXPR14 optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::forward(value_)) { } @@ -1410,7 +1411,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && !etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional(U&& value_) + ETL_CONSTEXPR20_STL optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::forward(value_)) { } @@ -1429,7 +1430,7 @@ namespace etl /// Emplace construct from arguments. //*************************************************************************** template - ETL_CONSTEXPR14 explicit optional(etl::in_place_t, Args&&... args) + ETL_CONSTEXPR14 explicit optional(etl::in_place_t, Args&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::in_place_t{}, etl::forward(args)...) { } @@ -1438,7 +1439,7 @@ namespace etl /// Emplace construct from arguments. //*************************************************************************** template - ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, Args&&... args) + ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, Args&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::in_place_t{}, etl::forward(args)...) { } @@ -1449,6 +1450,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR14 explicit optional(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : impl_t(etl::in_place_t{}, ilist, etl::forward(args)...) { } @@ -1458,6 +1460,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : impl_t(etl::in_place_t{}, ilist, etl::forward(args)...) { } @@ -1469,7 +1472,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(etl::nullopt_t) + ETL_CONSTEXPR14 optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1480,7 +1483,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(etl::nullopt_t) + ETL_CONSTEXPR20_STL optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1490,7 +1493,7 @@ namespace etl //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** - optional& operator=(etl::nullopt_t) + optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1503,7 +1506,7 @@ namespace etl /// Assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(const optional& other) + ETL_CONSTEXPR14 optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { impl_t::operator=(other); @@ -1514,7 +1517,7 @@ namespace etl /// Assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(const optional& other) + ETL_CONSTEXPR20_STL optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { impl_t::operator=(other); @@ -1537,7 +1540,7 @@ namespace etl /// Move assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(optional&& other) + ETL_CONSTEXPR14 optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { impl_t::operator=(etl::move(other)); @@ -1548,7 +1551,7 @@ namespace etl /// Move assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(optional&& other) + ETL_CONSTEXPR20_STL optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { impl_t::operator=(etl::move(other)); @@ -1565,7 +1568,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR14 optional& operator=(U&& value_) + ETL_CONSTEXPR14 optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { impl_t::operator=(etl::forward(value_)); @@ -1580,7 +1583,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && !etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional& operator=(U&& value_) + ETL_CONSTEXPR20_STL optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { impl_t::operator=(etl::forward(value_)); diff --git a/include/etl/parameter_pack.h b/include/etl/parameter_pack.h index 5dd21717..267065bb 100644 --- a/include/etl/parameter_pack.h +++ b/include/etl/parameter_pack.h @@ -34,11 +34,7 @@ SOFTWARE. #include -#if ETL_CPP11_NOT_SUPPORTED - #if !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR C++03 OR BELOW - #endif -#else +#if ETL_CPP11_SUPPORTED namespace etl { //*************************************************************************** diff --git a/include/etl/platform.h b/include/etl/platform.h index a9918b24..bbf3022c 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -489,6 +489,18 @@ SOFTWARE. #define ETL_ASSUME ETL_DO_NOTHING #endif +//************************************* +// C++26 +#if defined(__has_cpp_attribute) + #if __has_cpp_attribute(indeterminate) + #define ETL_INDETERMINATE [[indeterminate]] + #else + #define ETL_INDETERMINATE + #endif +#else + #define ETL_INDETERMINATE +#endif + //************************************* // Determine if the ETL can use char8_t type. #if ETL_NO_SMALL_CHAR_SUPPORT @@ -650,6 +662,7 @@ namespace etl static ETL_CONSTANT bool using_cpp17 = (ETL_USING_CPP17 == 1); static ETL_CONSTANT bool using_cpp20 = (ETL_USING_CPP20 == 1); static ETL_CONSTANT bool using_cpp23 = (ETL_USING_CPP23 == 1); + static ETL_CONSTANT bool using_cpp26 = (ETL_USING_CPP26 == 1); static ETL_CONSTANT bool using_gcc_compiler = (ETL_USING_GCC_COMPILER == 1); static ETL_CONSTANT bool using_microsoft_compiler = (ETL_USING_MICROSOFT_COMPILER == 1); static ETL_CONSTANT bool using_arm5_compiler = (ETL_USING_ARM5_COMPILER == 1); @@ -697,6 +710,9 @@ namespace etl static ETL_CONSTANT bool has_chrono_literals_microseconds = (ETL_HAS_CHRONO_LITERALS_DURATION == 1); static ETL_CONSTANT bool has_chrono_literals_nanoseconds = (ETL_HAS_CHRONO_LITERALS_DURATION == 1); static ETL_CONSTANT bool has_std_byteswap = (ETL_HAS_STD_BYTESWAP == 1); + static ETL_CONSTANT bool has_std_is_virtual_base_of = (ETL_HAS_STD_IS_VIRTUAL_BASE_OF == 1); + static ETL_CONSTANT bool has_std_trivially_relocatable = (ETL_HAS_STD_TRIVIALLY_RELOCATABLE == 1); + static ETL_CONSTANT bool has_std_atomic_min_max = (ETL_HAS_STD_ATOMIC_MIN_MAX == 1); static ETL_CONSTANT bool has_noexcept_function_type = (ETL_HAS_NOEXCEPT_FUNCTION_TYPE == 1); // Is... diff --git a/include/etl/priority_queue.h b/include/etl/priority_queue.h index e72d4908..2623fc07 100644 --- a/include/etl/priority_queue.h +++ b/include/etl/priority_queue.h @@ -439,7 +439,9 @@ namespace etl //************************************************************************* void clone(const ipriority_queue& other) { +#include "etl/private/diagnostic_uninitialized_push.h" assign(other.container.cbegin(), other.container.cend()); +#include "etl/private/diagnostic_pop.h" } #if ETL_USING_CPP11 diff --git a/include/etl/private/bitset_new.h b/include/etl/private/bitset_new.h index 89d4a0a8..19d21794 100644 --- a/include/etl/private/bitset_new.h +++ b/include/etl/private/bitset_new.h @@ -1078,7 +1078,7 @@ namespace etl /// Extract an value from multiple elements. //************************************************************************* template - static ETL_CONSTEXPR14 typename etl::make_unsigned::type extract_from_multiple_elements(const element_type* pbuffer, int element_index, + static ETL_CONSTEXPR14 typename etl::make_unsigned::type extract_from_multiple_elements(const element_type* pbuffer, size_t element_index, size_t active_bits_in_msb, size_t length) ETL_NOEXCEPT { typedef typename etl::make_unsigned::type unsigned_t; @@ -1133,8 +1133,8 @@ namespace etl unsigned_t value(0); - const int Msb_Element_Index = (position + length - 1) >> etl::log2::value; - const int Lsb_Element_Index = position >> etl::log2::value; + const size_t Msb_Element_Index = (position + length - 1) >> etl::log2::value; + const size_t Lsb_Element_Index = position >> etl::log2::value; // Is the value contained within one element? if (Msb_Element_Index == Lsb_Element_Index) @@ -1150,7 +1150,7 @@ namespace etl size_t active_bits_in_msb = (position + length) - (static_cast(Msb_Element_Index) * Bits_Per_Element); // Start with index of the element containing the msb. - int element_index = Msb_Element_Index; + size_t element_index = Msb_Element_Index; value = extract_from_multiple_elements(pbuffer, element_index, active_bits_in_msb, length); } @@ -1169,7 +1169,7 @@ namespace etl { typedef typename etl::make_unsigned::type unsigned_t; - const int Element_Index = (Position + Length - 1) >> etl::log2::value; + const size_t Element_Index = (Position + Length - 1) >> etl::log2::value; const unsigned_t Mask = etl::lsb_mask::value; const unsigned_t Shift = Position % Bits_Per_Element; @@ -1186,7 +1186,7 @@ namespace etl extract_from_buffer(const_pointer pbuffer) { // Start with index of the element containing the msb. - const int Msb_Element_Index = (Position + Length - 1) >> etl::log2::value; + const size_t Msb_Element_Index = (Position + Length - 1) >> etl::log2::value; // Get the number of active bits in the first element const size_t Active_Bits_In_Msb = ((Position + Length - 1) % Bits_Per_Element) + 1; diff --git a/include/etl/private/chrono/year_month_weekday.h b/include/etl/private/chrono/year_month_weekday.h index c557138a..8d7f4d52 100644 --- a/include/etl/private/chrono/year_month_weekday.h +++ b/include/etl/private/chrono/year_month_weekday.h @@ -174,11 +174,11 @@ namespace etl unsigned int target_wd = ymwd.weekday().c_encoding(); unsigned int target_index = ymwd.index(); - etl::chrono::weekday first_weekday(static_cast(sd.time_since_epoch().count())); + etl::chrono::weekday first_weekday(sd); unsigned int first_wd = first_weekday.c_encoding(); unsigned int offset = (target_wd - first_wd + 7U) % 7U; - unsigned int day_of_month = offset + (target_index - 1U) * 7U; + unsigned int day_of_month = 1U + offset + (target_index - 1U) * 7U; etl::chrono::year_month_day result(year(), month(), etl::chrono::day(day_of_month)); @@ -382,7 +382,7 @@ namespace etl { etl::chrono::year_month_day ymd(year(), month(), etl::chrono::day(d)); etl::chrono::sys_days ymd_sys_days = static_cast(ymd); - etl::chrono::weekday wd(static_cast(ymd_sys_days.time_since_epoch().count())); + etl::chrono::weekday wd(ymd_sys_days); if (wd == weekday()) { diff --git a/include/etl/private/delegate_cpp11.h b/include/etl/private/delegate_cpp11.h index 33d993e2..9664797b 100644 --- a/include/etl/private/delegate_cpp11.h +++ b/include/etl/private/delegate_cpp11.h @@ -172,7 +172,7 @@ namespace etl //************************************************************************* // Construct from a function pointer. //************************************************************************* - delegate(function_ptr fp) ETL_NOEXCEPT + explicit delegate(function_ptr fp) ETL_NOEXCEPT { assign(fp, function_ptr_stub); } @@ -534,7 +534,14 @@ namespace etl //************************************************************************* delegate& operator=(function_ptr fp) ETL_NOEXCEPT { - assign(fp, function_ptr_stub); + if (fp == ETL_NULLPTR) + { + invocation.clear(); + } + else + { + assign(fp, function_ptr_stub); + } return *this; } diff --git a/include/etl/private/diagnostic_sign_conversion_push.h b/include/etl/private/diagnostic_sign_conversion_push.h new file mode 100644 index 00000000..50c0532e --- /dev/null +++ b/include/etl/private/diagnostic_sign_conversion_push.h @@ -0,0 +1,44 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +/* + * The header include guard has been intentionally omitted. + * This file is intended to evaluated multiple times by design. + */ + +#if defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +#if defined(__clang__) || defined(__llvm__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wsign-conversion" +#endif diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index 5598f896..3a95502a 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -486,7 +486,7 @@ namespace etl /// alternative (index() is zero). //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant() + ETL_CONSTEXPR14 variant() ETL_NOEXCEPT_IF(etl::is_nothrow_default_constructible >::value) { using type = type_from_index<0U>; @@ -501,7 +501,7 @@ namespace etl //*************************************************************************** #include "diagnostic_uninitialized_push.h" template , variant>::value, int> = 0> - ETL_CONSTEXPR14 variant(T&& value) + ETL_CONSTEXPR14 variant(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, T&&>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -518,6 +518,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -534,6 +535,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : type_id(Index) { using type = type_from_index; @@ -552,6 +554,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t, std::initializer_list init, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -568,6 +571,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t, std::initializer_list init, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) : type_id(Index) { using type = type_from_index; @@ -585,7 +589,7 @@ namespace etl ///\param other The other variant object to copy. //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant(const variant& other) + ETL_CONSTEXPR14 variant(const variant& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) : operation(other.operation) , type_id(other.type_id) { @@ -605,7 +609,7 @@ namespace etl ///\param other The other variant object to copy. //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant(variant&& other) + ETL_CONSTEXPR14 variant(variant&& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) : operation(other.operation) , type_id(other.type_id) { @@ -623,7 +627,7 @@ namespace etl //*************************************************************************** /// Destructor. //*************************************************************************** - ~variant() + ~variant() ETL_NOEXCEPT { if (!valueless_by_exception()) { @@ -638,7 +642,7 @@ namespace etl /// Emplace by type with variadic constructor parameters. //*************************************************************************** template - T& emplace(TArgs&&... args) + T& emplace(TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { static_assert(etl::is_one_of::value, "Unsupported type"); @@ -664,6 +668,7 @@ namespace etl //*************************************************************************** template T& emplace(std::initializer_list il, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) { static_assert(etl::is_one_of::value, "Unsupported type"); @@ -689,6 +694,7 @@ namespace etl //*************************************************************************** template typename etl::variant_alternative_t >& emplace(TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { static_assert(Index < sizeof...(TTypes), "Index out of range"); @@ -714,6 +720,7 @@ namespace etl //*************************************************************************** template typename etl::variant_alternative_t >& emplace(std::initializer_list il, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) { static_assert(Index < sizeof...(TTypes), "Index out of range"); @@ -739,7 +746,7 @@ namespace etl ///\param value The value to assign. //*************************************************************************** template , variant>::value, int> = 0> - variant& operator=(T&& value) + variant& operator=(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, T&&>::value)) { using type = etl::remove_cvref_t; @@ -762,7 +769,7 @@ namespace etl /// Assignment operator for variant type. ///\param other The variant to assign. //*************************************************************************** - variant& operator=(const variant& other) + variant& operator=(const variant& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) { if (this != &other) { @@ -791,7 +798,7 @@ namespace etl /// Assignment operator for variant type. ///\param other The variant to assign. //*************************************************************************** - variant& operator=(variant&& other) + variant& operator=(variant&& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) { if (this != &other) { diff --git a/include/etl/profiles/cpp20.h b/include/etl/profiles/cpp20.h new file mode 100644 index 00000000..ea1fa98a --- /dev/null +++ b/include/etl/profiles/cpp20.h @@ -0,0 +1,49 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP20_INCLUDED +#define ETL_CPP20_INCLUDED + +//***************************************************************************** +// Generic C++20 +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 + +#endif diff --git a/include/etl/profiles/cpp20_no_stl.h b/include/etl/profiles/cpp20_no_stl.h new file mode 100644 index 00000000..c997cdc8 --- /dev/null +++ b/include/etl/profiles/cpp20_no_stl.h @@ -0,0 +1,50 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP20_NO_STL_INCLUDED +#define ETL_CPP20_NO_STL_INCLUDED + +//***************************************************************************** +// Generic C++20 without STL support +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 +#define ETL_NO_STL + +#endif diff --git a/include/etl/profiles/cpp23.h b/include/etl/profiles/cpp23.h new file mode 100644 index 00000000..21fc36f0 --- /dev/null +++ b/include/etl/profiles/cpp23.h @@ -0,0 +1,50 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP23_INCLUDED +#define ETL_CPP23_INCLUDED + +//***************************************************************************** +// Generic C++23 +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_CPP23_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 + +#endif diff --git a/include/etl/profiles/cpp23_no_stl.h b/include/etl/profiles/cpp23_no_stl.h new file mode 100644 index 00000000..d06a8545 --- /dev/null +++ b/include/etl/profiles/cpp23_no_stl.h @@ -0,0 +1,51 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP23_NO_STL_INCLUDED +#define ETL_CPP23_NO_STL_INCLUDED + +//***************************************************************************** +// Generic C++23 without STL support +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_CPP23_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 +#define ETL_NO_STL + +#endif diff --git a/include/etl/profiles/cpp26.h b/include/etl/profiles/cpp26.h new file mode 100644 index 00000000..8ba60ee3 --- /dev/null +++ b/include/etl/profiles/cpp26.h @@ -0,0 +1,51 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP26_INCLUDED +#define ETL_CPP26_INCLUDED + +//***************************************************************************** +// Generic C++26 +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_CPP23_SUPPORTED 1 +#define ETL_CPP26_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 + +#endif diff --git a/include/etl/profiles/cpp26_no_stl.h b/include/etl/profiles/cpp26_no_stl.h new file mode 100644 index 00000000..76dcf143 --- /dev/null +++ b/include/etl/profiles/cpp26_no_stl.h @@ -0,0 +1,52 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CPP26_NO_STL_INCLUDED +#define ETL_CPP26_NO_STL_INCLUDED + +//***************************************************************************** +// Generic C++26 without STL support +//***************************************************************************** + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE +#define ETL_COMPILER_GENERIC +#define ETL_CPP11_SUPPORTED 1 +#define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 1 +#define ETL_CPP20_SUPPORTED 1 +#define ETL_CPP23_SUPPORTED 1 +#define ETL_CPP26_SUPPORTED 1 +#define ETL_NO_NULLPTR_SUPPORT 0 +#define ETL_NO_LARGE_CHAR_SUPPORT 0 +#define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 +#define ETL_NO_STL + +#endif diff --git a/include/etl/profiles/determine_builtin_support.h b/include/etl/profiles/determine_builtin_support.h index 4a303fc0..da15062a 100644 --- a/include/etl/profiles/determine_builtin_support.h +++ b/include/etl/profiles/determine_builtin_support.h @@ -41,6 +41,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE 1 #endif + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE 1 + #endif + + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE 1 + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1 #endif @@ -60,7 +68,10 @@ SOFTWARE. #if !defined(ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED) #define ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED 1 #endif +#endif +#if defined(ETL_USE_BUILTIN_MEM_FUNCTIONS) // Set all of them to be true if not + // already defined #if !defined(ETL_USING_BUILTIN_MEMCPY) #define ETL_USING_BUILTIN_MEMCPY 1 #endif @@ -93,6 +104,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE __has_builtin(__is_constructible) #endif + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE __has_builtin(__is_nothrow_constructible) + #endif + + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE __has_builtin(__is_nothrow_assignable) + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE (__has_builtin(__has_trivial_constructor) || __has_builtin(__is_trivially_constructible)) #endif @@ -132,6 +151,20 @@ SOFTWARE. #if !defined(ETL_USING_BUILTIN_MEMCHR) #define ETL_USING_BUILTIN_MEMCHR __has_builtin(__builtin_memchr) #endif + + #if !defined(ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF) + #define ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF __has_builtin(__is_virtual_base_of) + #endif + + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE __has_builtin(__is_trivially_relocatable) + #endif + + // __builtin_is_cpp_trivially_relocatable replaces __is_trivially_relocatable by an + // effort of standardization for newer C++ standards + #if !defined(ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE) + #define ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE __has_builtin(__builtin_is_cpp_trivially_relocatable) + #endif #endif // The default. Set to 0, if not already set. @@ -143,6 +176,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE 0 #endif +#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE 0 +#endif + +#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE 0 +#endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0 #endif @@ -183,24 +224,41 @@ SOFTWARE. #define ETL_USING_BUILTIN_MEMCHR 0 #endif +#if !defined(ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF) + #define ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF 0 +#endif + +#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE 0 +#endif + +#if !defined(ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE) + #define ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE 0 +#endif + namespace etl { namespace traits { // Documentation: https://www.etlcpp.com/etl_traits.html - static ETL_CONSTANT bool using_builtin_is_assignable = (ETL_USING_BUILTIN_IS_ASSIGNABLE == 1); - static ETL_CONSTANT bool using_builtin_is_constructible = (ETL_USING_BUILTIN_IS_CONSTRUCTIBLE == 1); - static ETL_CONSTANT bool using_builtin_is_trivially_constructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE == 1); - static ETL_CONSTANT bool using_builtin_is_trivially_destructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE == 1); - static ETL_CONSTANT bool using_builtin_is_trivially_copyable = (ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE == 1); - static ETL_CONSTANT bool using_builtin_underlying_type = (ETL_USING_BUILTIN_UNDERLYING_TYPE == 1); - static ETL_CONSTANT bool using_builtin_is_constant_evaluated = (ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1); - static ETL_CONSTANT bool using_builtin_memcpy = (ETL_USING_BUILTIN_MEMCPY == 1); - static ETL_CONSTANT bool using_builtin_memmove = (ETL_USING_BUILTIN_MEMMOVE == 1); - static ETL_CONSTANT bool using_builtin_memset = (ETL_USING_BUILTIN_MEMSET == 1); - static ETL_CONSTANT bool using_builtin_memcmp = (ETL_USING_BUILTIN_MEMCMP == 1); - static ETL_CONSTANT bool using_builtin_memchr = (ETL_USING_BUILTIN_MEMCHR == 1); + static ETL_CONSTANT bool using_builtin_is_assignable = (ETL_USING_BUILTIN_IS_ASSIGNABLE == 1); + static ETL_CONSTANT bool using_builtin_is_constructible = (ETL_USING_BUILTIN_IS_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_nothrow_constructible = (ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_nothrow_assignable = (ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE == 1); + static ETL_CONSTANT bool using_builtin_is_trivially_constructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_trivially_destructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_trivially_copyable = (ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE == 1); + static ETL_CONSTANT bool using_builtin_underlying_type = (ETL_USING_BUILTIN_UNDERLYING_TYPE == 1); + static ETL_CONSTANT bool using_builtin_is_constant_evaluated = (ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1); + static ETL_CONSTANT bool using_builtin_memcpy = (ETL_USING_BUILTIN_MEMCPY == 1); + static ETL_CONSTANT bool using_builtin_memmove = (ETL_USING_BUILTIN_MEMMOVE == 1); + static ETL_CONSTANT bool using_builtin_memset = (ETL_USING_BUILTIN_MEMSET == 1); + static ETL_CONSTANT bool using_builtin_memcmp = (ETL_USING_BUILTIN_MEMCMP == 1); + static ETL_CONSTANT bool using_builtin_memchr = (ETL_USING_BUILTIN_MEMCHR == 1); + static ETL_CONSTANT bool using_builtin_is_virtual_base_of = (ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF == 1); + static ETL_CONSTANT bool using_builtin_is_trivially_relocatable = (ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE == 1); + static ETL_CONSTANT bool using_builtin_builtin_is_cpp_trivially_relocatable = (ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE == 1); } // namespace traits } // namespace etl diff --git a/include/etl/profiles/determine_compiler_language_support.h b/include/etl/profiles/determine_compiler_language_support.h index 645bd06d..58bda6ef 100644 --- a/include/etl/profiles/determine_compiler_language_support.h +++ b/include/etl/profiles/determine_compiler_language_support.h @@ -35,6 +35,31 @@ SOFTWARE. #include "determine_compiler.h" +// Determine C++26 support +#if !defined(ETL_CPP26_SUPPORTED) + #if defined(__cplusplus) + #if defined(ETL_COMPILER_MICROSOFT) + #define ETL_CPP26_SUPPORTED (__cplusplus >= 202400L) + #elif defined(ETL_COMPILER_ARM5) + #define ETL_CPP26_SUPPORTED 0 + #elif defined(ETL_COMPILER_GCC) + #define ETL_CPP26_SUPPORTED (__cplusplus >= 202400L) + #else + #define ETL_CPP26_SUPPORTED (__cplusplus >= 202400L) + #endif + #else + #define ETL_CPP26_SUPPORTED 0 + #endif +#endif + +#if ETL_CPP26_SUPPORTED + #define ETL_CPP11_SUPPORTED 1 + #define ETL_CPP14_SUPPORTED 1 + #define ETL_CPP17_SUPPORTED 1 + #define ETL_CPP20_SUPPORTED 1 + #define ETL_CPP23_SUPPORTED 1 +#endif + // Determine C++23 support #if !defined(ETL_CPP23_SUPPORTED) #if defined(__cplusplus) @@ -162,6 +187,7 @@ SOFTWARE. #define ETL_CPP17_NOT_SUPPORTED (!ETL_CPP17_SUPPORTED) #define ETL_CPP20_NOT_SUPPORTED (!ETL_CPP20_SUPPORTED) #define ETL_CPP23_NOT_SUPPORTED (!ETL_CPP23_SUPPORTED) +#define ETL_CPP26_NOT_SUPPORTED (!ETL_CPP26_SUPPORTED) // 'Using' macros #define ETL_USING_CPP11 (ETL_CPP11_SUPPORTED == 1) @@ -169,12 +195,14 @@ SOFTWARE. #define ETL_USING_CPP17 (ETL_CPP17_SUPPORTED == 1) #define ETL_USING_CPP20 (ETL_CPP20_SUPPORTED == 1) #define ETL_USING_CPP23 (ETL_CPP23_SUPPORTED == 1) +#define ETL_USING_CPP26 (ETL_CPP26_SUPPORTED == 1) #define ETL_NOT_USING_CPP11 (ETL_CPP11_SUPPORTED == 0) #define ETL_NOT_USING_CPP14 (ETL_CPP14_SUPPORTED == 0) #define ETL_NOT_USING_CPP17 (ETL_CPP17_SUPPORTED == 0) #define ETL_NOT_USING_CPP20 (ETL_CPP20_SUPPORTED == 0) #define ETL_NOT_USING_CPP23 (ETL_CPP23_SUPPORTED == 0) +#define ETL_NOT_USING_CPP26 (ETL_CPP26_SUPPORTED == 0) #if !defined(ETL_NO_NULLPTR_SUPPORT) #define ETL_NO_NULLPTR_SUPPORT ETL_NOT_USING_CPP11 @@ -198,7 +226,9 @@ SOFTWARE. // Language standard #if !defined(ETL_LANGUAGE_STANDARD) - #if ETL_USING_CPP23 + #if ETL_USING_CPP26 + #define ETL_LANGUAGE_STANDARD 26 + #elif ETL_USING_CPP23 #define ETL_LANGUAGE_STANDARD 23 #elif ETL_USING_CPP20 #define ETL_LANGUAGE_STANDARD 20 @@ -227,10 +257,37 @@ SOFTWARE. #define ETL_HAS_STD_BYTESWAP 1 #endif #endif + + #if defined(__cpp_lib_is_virtual_base_of) + #if __cpp_lib_is_virtual_base_of != 0 + #define ETL_HAS_STD_IS_VIRTUAL_BASE_OF 1 + #endif + #endif + + #if defined(__cpp_lib_trivially_relocatable) + #if __cpp_lib_trivially_relocatable != 0 + #define ETL_HAS_STD_TRIVIALLY_RELOCATABLE 1 + #endif + #endif + + #if defined(__cpp_lib_atomic_min_max) + #if __cpp_lib_atomic_min_max != 0 + #define ETL_HAS_STD_ATOMIC_MIN_MAX 1 + #endif + #endif #endif #endif #ifndef ETL_HAS_STD_BYTESWAP #define ETL_HAS_STD_BYTESWAP 0 #endif +#ifndef ETL_HAS_STD_IS_VIRTUAL_BASE_OF + #define ETL_HAS_STD_IS_VIRTUAL_BASE_OF 0 +#endif +#ifndef ETL_HAS_STD_TRIVIALLY_RELOCATABLE + #define ETL_HAS_STD_TRIVIALLY_RELOCATABLE 0 +#endif +#ifndef ETL_HAS_STD_ATOMIC_MIN_MAX + #define ETL_HAS_STD_ATOMIC_MIN_MAX 0 +#endif #endif diff --git a/include/etl/ranges.h b/include/etl/ranges.h index 4e1ba4b1..8e875b83 100644 --- a/include/etl/ranges.h +++ b/include/etl/ranges.h @@ -2975,7 +2975,7 @@ namespace etl iterator() = default; iterator(const_iterator_type current, const_iterator_type segment_end, bool is_end) - : _current(current) + : _current_it(current) , _segment_end(segment_end) , _is_end(is_end || (current == segment_end)) { @@ -2983,18 +2983,18 @@ namespace etl reference operator*() const { - return *_current; + return *_current_it; } pointer operator->() const { - return &(*_current); + return &(*_current_it); } iterator& operator++() { - ++_current; - if (_current == _segment_end) + ++_current_it; + if (_current_it == _segment_end) { _is_end = true; } @@ -3018,7 +3018,7 @@ namespace etl { return false; } - return _current == other._current; + return _current_it == other._current_it; } constexpr bool operator!=(const iterator& other) const @@ -3028,7 +3028,7 @@ namespace etl private: - const_iterator_type _current{}; + const_iterator_type _current_it{}; const_iterator_type _segment_end{}; bool _is_end = true; }; @@ -3379,7 +3379,7 @@ namespace etl concat_iterator(size_t index, concat_view& view, iterator_variant_type current) : _ranges_index{index} , _view(view) - , _current(current) + , _current_it(current) { } @@ -3387,7 +3387,7 @@ namespace etl constexpr reference operator*() const { - return _view.get_value(_ranges_index, _current); + return _view.get_value(_ranges_index, _current_it); } constexpr decltype(auto) operator[](difference_type pos) const @@ -3397,14 +3397,14 @@ namespace etl { for (difference_type i = 0; i < pos; ++i) { - tmp._view.advance(tmp._ranges_index, tmp._current, 1); + tmp._view.advance(tmp._ranges_index, tmp._current_it, 1); } } if (pos < 0) { for (difference_type i = 0; i < -pos; ++i) { - tmp._view.advance(tmp._ranges_index, tmp._current, -1); + tmp._view.advance(tmp._ranges_index, tmp._current_it, -1); } } return *tmp; @@ -3412,27 +3412,27 @@ namespace etl constexpr concat_iterator& operator++() { - _view.advance(_ranges_index, _current, 1); + _view.advance(_ranges_index, _current_it, 1); return *this; } constexpr concat_iterator operator++(int) { auto result = *this; - _view.advance(_ranges_index, _current, 1); + _view.advance(_ranges_index, _current_it, 1); return result; } constexpr concat_iterator& operator--() { - _view.advance(_ranges_index, _current, -1); + _view.advance(_ranges_index, _current_it, -1); return *this; } constexpr concat_iterator operator--(int) { auto result = *this; - _view.advance(_ranges_index, _current, -1); + _view.advance(_ranges_index, _current_it, -1); return result; } @@ -3440,7 +3440,7 @@ namespace etl { for (difference_type i = 0; i < n; ++i) { - _view.advance(_ranges_index, _current, 1); + _view.advance(_ranges_index, _current_it, 1); } return *this; } @@ -3449,7 +3449,7 @@ namespace etl { for (difference_type i = 0; i < n; ++i) { - _view.advance(_ranges_index, _current, -1); + _view.advance(_ranges_index, _current_it, -1); } return *this; } @@ -3457,12 +3457,12 @@ namespace etl friend constexpr bool operator==(const concat_iterator& x, etl::default_sentinel_t) { return x._ranges_index == x._view.number_of_ranges - 1 - && etl::get(x._current) == etl::get(x._view).end(); + && etl::get(x._current_it) == etl::get(x._view).end(); } friend constexpr bool operator==(const concat_iterator& x, const concat_iterator& y) { - return x._ranges_index == y._ranges_index && x._current.index() == y._current.index() && x._current == y._current; + return x._ranges_index == y._ranges_index && x._current_it.index() == y._current_it.index() && x._current_it == y._current_it; } friend constexpr bool operator!=(const concat_iterator& x, etl::default_sentinel_t) @@ -3479,7 +3479,7 @@ namespace etl size_t _ranges_index; const concat_view& _view; - iterator_variant_type _current; + iterator_variant_type _current_it; }; template @@ -5746,7 +5746,7 @@ namespace etl using iterator_category = ETL_OR_STD::forward_iterator_tag; constexpr cartesian_product_iterator(iterators_type current, iterators_type begins, iterators_type ends, bool is_end = false) - : _current(current) + : _current_it(current) , _begins(begins) , _ends(ends) , _is_end(is_end) @@ -5799,7 +5799,7 @@ namespace etl template constexpr etl::enable_if_t<(I > 0)> increment_at() { - auto& it = etl::get(_current); + auto& it = etl::get(_current_it); ++it; if (it == etl::get(_ends)) { @@ -5811,7 +5811,7 @@ namespace etl template constexpr etl::enable_if_t<(I == 0)> increment_at() { - auto& it = etl::get<0>(_current); + auto& it = etl::get<0>(_current_it); ++it; if (it == etl::get<0>(_ends)) { @@ -5822,16 +5822,16 @@ namespace etl template constexpr value_type deref(etl::index_sequence) const { - return value_type(*etl::get(_current)...); + return value_type(*etl::get(_current_it)...); } template constexpr bool all_equal(const cartesian_product_iterator& other, etl::index_sequence) const { - return ((etl::get(_current) == etl::get(other._current)) && ...); + return ((etl::get(_current_it) == etl::get(other._current_it)) && ...); } - iterators_type _current; + iterators_type _current_it; iterators_type _begins; iterators_type _ends; bool _is_end; diff --git a/include/etl/ratio.h b/include/etl/ratio.h index f4476dff..21a2d894 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -161,12 +161,20 @@ namespace etl #endif //*********************************************************************** -/// Predefined ration types. +/// Predefined ratio types. //*********************************************************************** #if INT_MAX > INT32_MAX - typedef ratio<1, 1000000000000000000> atto; - typedef ratio<1, 1000000000000000> femto; - typedef ratio<1, 1000000000000> pico; + // 2022 SI prefix (10^-30) + typedef ratio<1, 1000000000000000000LL * 1000000000000LL> quecto; + // 2022 SI prefix (10^-27) + typedef ratio<1, 1000000000000000000LL * 1000000000LL> ronto; + // 10^-24 + typedef ratio<1, 1000000000000000000LL * 1000000LL> yocto; + // 10^-21 + typedef ratio<1, 1000000000000000000LL * 1000LL> zepto; + typedef ratio<1, 1000000000000000000> atto; + typedef ratio<1, 1000000000000000> femto; + typedef ratio<1, 1000000000000> pico; #endif #if (INT_MAX >= INT32_MAX) @@ -192,6 +200,14 @@ namespace etl typedef ratio<1000000000000, 1> tera; typedef ratio<1000000000000000, 1> peta; typedef ratio<1000000000000000000, 1> exa; + // 10^21 + typedef ratio<1000000000000000000LL * 1000LL, 1> zetta; + // 10^24 + typedef ratio<1000000000000000000LL * 1000000LL, 1> yotta; + // 2022 SI prefix (10^27) + typedef ratio<1000000000000000000LL * 1000000000LL, 1> ronna; + // 2022 SI prefix (10^30) + typedef ratio<1000000000000000000LL * 1000000000000LL, 1> quetta; #endif /// An approximation of Pi. diff --git a/include/etl/result.h b/include/etl/result.h index 5b5fcad8..22b5f92c 100644 --- a/include/etl/result.h +++ b/include/etl/result.h @@ -38,11 +38,7 @@ SOFTWARE. #include "optional.h" #include "variant.h" -#if ETL_CPP11_NOT_SUPPORTED - #if !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR C++03 OR BELOW - #endif -#else +#if ETL_CPP11_SUPPORTED namespace etl { @@ -70,7 +66,6 @@ namespace etl { } - #if ETL_CPP11_SUPPORTED //******************************************* /// Move constructor //******************************************* @@ -78,7 +73,6 @@ namespace etl : data(etl::move(other.data)) { } - #endif //******************************************* // Construct from a value @@ -104,15 +98,13 @@ namespace etl { } - //******************************************* - /// Move construct from error - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Move construct from error + //******************************************* result(TError&& error) : data(etl::move(error)) { } - #endif //******************************************* /// Copy assign @@ -141,16 +133,14 @@ namespace etl return *this; } - //******************************************* - /// Move assign from value - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Move assign from value + //******************************************* result& operator=(TValue&& value) { data = etl::move(value); return *this; } - #endif //******************************************* /// Copy assign from error @@ -161,16 +151,14 @@ namespace etl return *this; } - //******************************************* - /// Move assign from error - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Move assign from error + //******************************************* result& operator=(TError&& error) { data = etl::move(error); return *this; } - #endif //******************************************* /// true if result contains a value @@ -223,16 +211,14 @@ namespace etl return etl::get(data); } - //******************************************* - /// Returns an rvalue reference to the error. - /// Undefined if the result does not contain an error. - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Returns an rvalue reference to the error. + /// Undefined if the result does not contain an error. + //******************************************* TError&& error() { return etl::move(etl::get(data)); } - #endif private: @@ -280,15 +266,13 @@ namespace etl { } - //******************************************* - /// Move construct from error - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Move construct from error + //******************************************* result(TError&& error) : data(etl::move(error)) { } - #endif //******************************************* /// Copy assign from error @@ -299,16 +283,14 @@ namespace etl return *this; } - //******************************************* - /// Move assign from error - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Move assign from error + //******************************************* result& operator=(TError&& error) { data = etl::move(error); return *this; } - #endif //******************************************* /// true if result contains a value @@ -343,16 +325,14 @@ namespace etl return data.value(); } - //******************************************* - /// Returns an rvalue reference to the error. - /// Undefined if the result does not contain an error. - //******************************************* - #if ETL_CPP11_SUPPORTED + //******************************************* + /// Returns an rvalue reference to the error. + /// Undefined if the result does not contain an error. + //******************************************* TError&& error() { return etl::move(data.value()); } - #endif private: diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index b56a9dc5..26ae700c 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -36,6 +36,8 @@ SOFTWARE. #include "type_traits.h" #include "utility.h" +#if ETL_USING_CPP11 + namespace etl { namespace private_rounded_integral_division @@ -565,7 +567,7 @@ namespace etl // Work with magnitudes in unsigned form (avoids abs() overflow for // T::min()). - typedef typename std::make_unsigned::type utype; + typedef typename etl::make_unsigned::type utype; const utype abs_denominator = (denominator < 0) ? (utype(0) - utype(denominator)) : utype(denominator); const utype abs_remainder = (remainder < 0) ? (utype(0) - utype(remainder)) : utype(remainder); const utype half_denominator = abs_denominator / 2U; @@ -784,3 +786,4 @@ namespace etl } // namespace etl #endif +#endif diff --git a/include/etl/signal.h b/include/etl/signal.h index 0f198824..3392cff6 100644 --- a/include/etl/signal.h +++ b/include/etl/signal.h @@ -35,10 +35,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #if ETL_USING_CPP11 #include "algorithm.h" diff --git a/include/etl/tuple.h b/include/etl/tuple.h index 31cdce5f..f76c0a62 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -31,10 +31,6 @@ SOFTWARE. #include "platform.h" -#if ETL_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST) - #error NOT SUPPORTED FOR C++03 OR BELOW -#endif - #if ETL_USING_CPP11 #if ETL_USING_STL diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 411632ff..2600da96 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -1170,6 +1170,21 @@ namespace etl inline constexpr bool is_base_of_v = is_base_of::value; #endif + //*************************************************************************** + /// is_virtual_base_of + /// Determines if TBase is a virtual base class of TDerived + #if ETL_USING_CPP11 && ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF + template + struct is_virtual_base_of : etl::bool_constant<__is_virtual_base_of(TBase, TDerived)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_virtual_base_of_v = is_virtual_base_of::value; + #endif + #endif + //*************************************************************************** /// add_lvalue_reference template @@ -2017,6 +2032,32 @@ namespace etl inline constexpr bool is_base_of_v = std::is_base_of_v; #endif + //*************************************************************************** + /// is_virtual_base_of + /// Determines if TBase is a virtual base class of TDerived + ///\ingroup type_traits + #if ETL_HAS_STD_IS_VIRTUAL_BASE_OF + template + struct is_virtual_base_of : std::is_virtual_base_of + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_virtual_base_of_v = std::is_virtual_base_of_v; + #endif + #elif ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF + template + struct is_virtual_base_of : etl::bool_constant<__is_virtual_base_of(TBase, TDerived)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_virtual_base_of_v = is_virtual_base_of::value; + #endif + #endif + //*************************************************************************** /// is_class template @@ -2594,6 +2635,41 @@ namespace etl template using is_move_assignable = std::is_move_assignable; + //********************************************* + // is_nothrow_constructible + template + using is_nothrow_constructible = std::is_nothrow_constructible; + + //********************************************* + // is_nothrow_default_constructible + template + using is_nothrow_default_constructible = std::is_nothrow_default_constructible; + + //********************************************* + // is_nothrow_copy_constructible + template + using is_nothrow_copy_constructible = std::is_nothrow_copy_constructible; + + //********************************************* + // is_nothrow_move_constructible + template + using is_nothrow_move_constructible = std::is_nothrow_move_constructible; + + //********************************************* + // is_nothrow_assignable + template + using is_nothrow_assignable = std::is_nothrow_assignable; + + //********************************************* + // is_nothrow_copy_assignable + template + using is_nothrow_copy_assignable = std::is_nothrow_copy_assignable; + + //********************************************* + // is_nothrow_move_assignable + template + using is_nothrow_move_assignable = std::is_nothrow_move_assignable; + //********************************************* // is_trivially_constructible #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED @@ -2647,6 +2723,40 @@ namespace etl using is_trivially_copyable = etl::bool_constant::value || etl::is_pointer::value>; #endif + //********************************************* + // is_trivially_relocatable + #if ETL_HAS_STD_TRIVIALLY_RELOCATABLE && ETL_USING_STL + template + using is_trivially_relocatable = std::is_trivially_relocatable; + #elif ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE + template + using is_trivially_relocatable = etl::bool_constant<__builtin_is_cpp_trivially_relocatable(T)>; + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + template + using is_trivially_relocatable = etl::bool_constant<__is_trivially_relocatable(T)>; + #else + template + using is_trivially_relocatable = etl::bool_constant::value && etl::is_trivially_destructible::value>; + #endif + + //********************************************* + // is_nothrow_relocatable + // A type is nothrow relocatable if it is trivially relocatable, or + // if it has a nothrow move constructor and nothrow destructor. + #if ETL_HAS_STD_TRIVIALLY_RELOCATABLE && ETL_USING_STL + template + using is_nothrow_relocatable = std::is_nothrow_relocatable; + #elif ETL_USING_STL + template + using is_nothrow_relocatable = etl::bool_constant< etl::is_trivially_relocatable::value + || (std::is_nothrow_move_constructible::type>::value + && std::is_nothrow_destructible::type>::value)>; + #else + // Fallback: only trivially relocatable types are known to be nothrow relocatable + template + using is_nothrow_relocatable = etl::is_trivially_relocatable; + #endif + #elif defined(ETL_USE_TYPE_TRAITS_BUILTINS) && !defined(ETL_USER_DEFINED_TYPE_TRAITS) //********************************************* @@ -2723,6 +2833,71 @@ namespace etl }; #endif + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible + { + #if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE + static ETL_CONSTANT bool value = __is_nothrow_constructible(T, TArgs...); + #else + static ETL_CONSTANT bool value = etl::is_arithmetic::value || etl::is_pointer::value; + #endif + }; + + //********************************************* + // is_nothrow_default_constructible + template + struct is_nothrow_default_constructible : public etl::is_nothrow_constructible + { + }; + + //********************************************* + // is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible : public etl::is_nothrow_constructible::type> + { + }; + + //********************************************* + // is_nothrow_move_constructible + template + struct is_nothrow_move_constructible : public etl::is_nothrow_constructible::type> + { + }; + #endif + + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_assignable + template + struct is_nothrow_assignable + { + #if ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE + static ETL_CONSTANT bool value = __is_nothrow_assignable(T, U); + #else + static ETL_CONSTANT bool value = etl::is_arithmetic::value || etl::is_pointer::value; + #endif + }; + + //********************************************* + // is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable + : public etl::is_nothrow_assignable::type, typename etl::add_lvalue_reference::type> + { + }; + + //********************************************* + // is_nothrow_move_assignable + template + struct is_nothrow_move_assignable + : public etl::is_nothrow_assignable::type, typename etl::add_rvalue_reference::type> + { + }; + #endif + #if ETL_USING_CPP11 //********************************************* // is_trivially_constructible @@ -2800,6 +2975,31 @@ namespace etl static ETL_CONSTANT bool value = __is_trivially_copyable(T); }; + //********************************************* + // is_trivially_relocatable + template + struct is_trivially_relocatable + { + #if ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE + static ETL_CONSTANT bool value = __builtin_is_cpp_trivially_relocatable(T); + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + static ETL_CONSTANT bool value = __is_trivially_relocatable(T); + #else + static ETL_CONSTANT bool value = etl::is_trivially_copyable::value && etl::is_trivially_destructible::value; + #endif + }; + + //********************************************* + // is_nothrow_relocatable + // A type is nothrow relocatable if it is trivially relocatable, or + // if it has a nothrow move constructor and nothrow destructor. + template + struct is_nothrow_relocatable + { + // In builtins mode, conservatively use trivially_relocatable as the definition + static ETL_CONSTANT bool value = etl::is_trivially_relocatable::value; + }; + #elif defined(ETL_USER_DEFINED_TYPE_TRAITS) && !defined(ETL_USE_TYPE_TRAITS_BUILTINS) //********************************************* @@ -2894,6 +3094,104 @@ namespace etl template struct is_move_assignable; + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible_helper; + + template + struct is_nothrow_constructible_helper : public etl::true_type + { + }; + + template + struct is_nothrow_constructible_helper; + + template + struct is_nothrow_constructible : public is_nothrow_constructible_helper::value || etl::is_pointer::value, TArgs...> + { + }; + + //********************************************* + // is_nothrow_default_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_default_constructible; + + template + struct is_nothrow_default_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_default_constructible; + + //********************************************* + // is_nothrow_copy_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_copy_constructible; + + template + struct is_nothrow_copy_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_copy_constructible; + + //********************************************* + // is_nothrow_move_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_move_constructible; + + template + struct is_nothrow_move_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_move_constructible; + + //********************************************* + // is_nothrow_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_assignable; + + template + struct is_nothrow_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_assignable; + + //********************************************* + // is_nothrow_copy_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_copy_assignable; + + template + struct is_nothrow_copy_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_copy_assignable; + + //********************************************* + // is_nothrow_move_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_move_assignable; + + template + struct is_nothrow_move_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_move_assignable; + #endif + //********************************************* // is_trivially_constructible template ::value || etl::is_pointer::value> @@ -2959,6 +3257,33 @@ namespace etl template struct is_trivially_copyable; + //********************************************* + // is_trivially_relocatable + template ::value || etl::is_pointer::value> + struct is_trivially_relocatable; + + template + struct is_trivially_relocatable : public etl::true_type + { + }; + + template + struct is_trivially_relocatable; + + //********************************************* + // is_nothrow_relocatable + // In user-defined mode, users must specialize for non-trivially-relocatable types + template ::value || etl::is_pointer::value> + struct is_nothrow_relocatable; + + template + struct is_nothrow_relocatable : public etl::true_type + { + }; + + template + struct is_nothrow_relocatable; + #else //********************************************* @@ -3087,6 +3412,57 @@ namespace etl }; #endif + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_default_constructible + template + struct is_nothrow_default_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_move_constructible + template + struct is_nothrow_move_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_assignable + template + struct is_nothrow_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_move_assignable + template + struct is_nothrow_move_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + #endif + //********************************************* // is_trivially_constructible template @@ -3126,6 +3502,27 @@ namespace etl { }; + //********************************************* + // is_trivially_relocatable + template + #if ETL_USING_BUILTIN_BUILTIN_IS_CPP_TRIVIALLY_RELOCATABLE + struct is_trivially_relocatable : public etl::bool_constant<__builtin_is_cpp_trivially_relocatable(T)> + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + struct is_trivially_relocatable : public etl::bool_constant<__is_trivially_relocatable(T)> + #else + struct is_trivially_relocatable : public etl::bool_constant::value && etl::is_trivially_destructible::value> + #endif + { + }; + + //********************************************* + // is_nothrow_relocatable + // Fallback: only trivially relocatable types are known to be nothrow relocatable + template + struct is_nothrow_relocatable : public etl::is_trivially_relocatable + { + }; + #endif template @@ -3180,6 +3577,27 @@ namespace etl template inline constexpr bool is_move_assignable_v = etl::is_move_assignable::value; + template + inline constexpr bool is_nothrow_constructible_v = etl::is_nothrow_constructible::value; + + template + inline constexpr bool is_nothrow_default_constructible_v = etl::is_nothrow_default_constructible::value; + + template + inline constexpr bool is_nothrow_copy_constructible_v = etl::is_nothrow_copy_constructible::value; + + template + inline constexpr bool is_nothrow_move_constructible_v = etl::is_nothrow_move_constructible::value; + + template + inline constexpr bool is_nothrow_assignable_v = etl::is_nothrow_assignable::value; + + template + inline constexpr bool is_nothrow_copy_assignable_v = etl::is_nothrow_copy_assignable::value; + + template + inline constexpr bool is_nothrow_move_assignable_v = etl::is_nothrow_move_assignable::value; + template inline constexpr bool is_trivially_constructible_v = etl::is_trivially_constructible::value; @@ -3195,6 +3613,12 @@ namespace etl template inline constexpr bool is_trivially_copyable_v = etl::is_trivially_copyable::value; + template + inline constexpr bool is_trivially_relocatable_v = etl::is_trivially_relocatable::value; + + template + inline constexpr bool is_nothrow_relocatable_v = etl::is_nothrow_relocatable::value; + #endif #if ETL_USING_CPP11 diff --git a/include/etl/vector.h b/include/etl/vector.h index ba10ac79..ebdc5d1e 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -479,7 +479,9 @@ namespace etl { ETL_ASSERT_CHECK_PUSH_POP(size() != CAPACITY, ETL_ERROR(vector_full)); + #include "private/diagnostic_sign_conversion_push.h" ::new (p_end) T(etl::forward(args)...); + #include "private/diagnostic_pop.h" ++p_end; ETL_INCREMENT_DEBUG_COUNT; return back(); @@ -668,7 +670,9 @@ namespace etl (*position_).~T(); } + #include "private/diagnostic_sign_conversion_push.h" ::new (p) T(etl::forward(args)...); + #include "private/diagnostic_pop.h" return position_; } @@ -1014,7 +1018,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - ivector& operator=(ivector&& rhs) + ivector& operator=(ivector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1081,7 +1085,7 @@ namespace etl //********************************************************************* /// Constructor. //********************************************************************* - ivector(T* p_buffer_, size_t MAX_SIZE) + ivector(T* p_buffer_, size_t MAX_SIZE) ETL_NOEXCEPT : vector_base(MAX_SIZE) , p_buffer(p_buffer_) , p_end(p_buffer_) @@ -1284,7 +1288,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector() + vector() ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { this->initialise(); @@ -1363,7 +1367,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector(vector&& other) + vector(vector&& other) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { if (this != &other) @@ -1384,7 +1388,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector& operator=(vector&& rhs) + vector& operator=(vector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1409,7 +1413,7 @@ namespace etl #ifdef ETL_IVECTOR_REPAIR_ENABLE virtual #endif - ~vector() + ~vector() ETL_NOEXCEPT { this->clear(); } @@ -1466,7 +1470,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector_ext(void* buffer, size_t max_size) + vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(buffer), max_size) { this->initialise(); @@ -1546,7 +1550,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector_ext(vector_ext&& other, void* buffer, size_t max_size) + vector_ext(vector_ext&& other, void* buffer, size_t max_size) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) : etl::ivector(reinterpret_cast(buffer), max_size) { if (this != &other) @@ -1567,7 +1571,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector_ext& operator=(vector_ext&& rhs) + vector_ext& operator=(vector_ext&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1590,7 +1594,7 @@ namespace etl //************************************************************************* /// Destructor. //************************************************************************* - ~vector_ext() + ~vector_ext() ETL_NOEXCEPT { this->clear(); } @@ -1625,7 +1629,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector() + vector() ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { this->initialise(); @@ -1701,7 +1705,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector(vector&& other) + vector(vector&& other) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { (void)etl::ivector::operator=(etl::move(other)); @@ -1710,7 +1714,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector& operator=(vector&& rhs) + vector& operator=(vector&& rhs) ETL_NOEXCEPT { (void)etl::ivector::operator=(etl::move(rhs)); @@ -1765,7 +1769,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector_ext(void* buffer, size_t max_size) + vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(buffer), max_size) { this->initialise(); @@ -1872,7 +1876,7 @@ namespace etl //************************************************************************* /// Destructor. //************************************************************************* - ~vector_ext() + ~vector_ext() ETL_NOEXCEPT { this->clear(); } diff --git a/scripts/run-docker.sh b/scripts/run-docker.sh new file mode 100755 index 00000000..862cb436 --- /dev/null +++ b/scripts/run-docker.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Create docker image for development environment and enter container +# +# Run from project root directory +# + +set -e + +# Verify script is running from project root +if [ ! -d ".devcontainer" ]; then + echo "Error: This script must be run from the project root directory." >&2 + echo "The .devcontainer directory was not found." >&2 + exit 1 +fi + +docker build -t etl .devcontainer +docker run -it --rm -v "$(pwd)":/home/vscode/etl -u vscode -w /home/vscode/etl etl /bin/bash diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a559add4..a7e61fb9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,8 +83,9 @@ add_executable(etl_tests test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp test_circular_iterator.cpp - test_closure.cpp - test_closure_constexpr.cpp + test_closure_with_default_delegate.cpp + test_closure_with_default_delegate_constexpr.cpp + test_closure_with_inplace_function.cpp test_compare.cpp test_concepts.cpp test_constant.cpp @@ -384,6 +385,7 @@ option(ETL_NO_STL "No STL" OFF) set(EXTRA_COMPILE_OPTIONS "" CACHE STRING "Additional compiler options") set(EXTRA_LINK_OPTIONS "" CACHE STRING "Additional linker options") set(EXTRA_LINK_LIBS "" CACHE STRING "Additional libraries to link") +set(EXTRA_TESTING_FLAGS "" CACHE STRING "Additional testing flags for ctest") if (ETL_CXX_STANDARD MATCHES "98") message(STATUS "Compiling for C++98") @@ -404,10 +406,26 @@ elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) elseif (ETL_CXX_STANDARD MATCHES "23") - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Unsupported C++ standard") + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() if (NO_STL OR ETL_NO_STL) @@ -523,7 +541,7 @@ if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Cla target_link_options(etl_tests PRIVATE -fsanitize=address,undefined,bounds - ) + ) endif() endif () endif () @@ -537,7 +555,7 @@ target_link_libraries(etl_tests PRIVATE UnitTestpp ${EXTRA_LINK_LIBS}) enable_testing() # Enable the 'make test' CMake target using the executable defined above -add_test(NAME etl_unit_tests COMMAND etl_tests) +add_test(NAME etl_unit_tests COMMAND etl_tests ${EXTRA_TESTING_FLAGS}) # Since ctest will only show you the results of the single executable # define a target that will output all of the failing or passing tests diff --git a/test/etl_error_handler/assert_function/CMakeLists.txt b/test/etl_error_handler/assert_function/CMakeLists.txt index babd03cc..f9ac1b49 100644 --- a/test/etl_error_handler/assert_function/CMakeLists.txt +++ b/test/etl_error_handler/assert_function/CMakeLists.txt @@ -34,9 +34,27 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() if (ETL_OPTIMISATION MATCHES "-O1") diff --git a/test/etl_error_handler/exceptions/CMakeLists.txt b/test/etl_error_handler/exceptions/CMakeLists.txt index 2da119b0..eac58405 100644 --- a/test/etl_error_handler/exceptions/CMakeLists.txt +++ b/test/etl_error_handler/exceptions/CMakeLists.txt @@ -32,9 +32,27 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() if (ETL_OPTIMISATION MATCHES "-O1") diff --git a/test/etl_error_handler/log_errors/CMakeLists.txt b/test/etl_error_handler/log_errors/CMakeLists.txt index 337e6546..4c96e4de 100644 --- a/test/etl_error_handler/log_errors/CMakeLists.txt +++ b/test/etl_error_handler/log_errors/CMakeLists.txt @@ -18,7 +18,7 @@ if (ETL_CXX_STANDARD MATCHES "98") message(STATUS "Compiling for C++98") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 98) elseif (ETL_CXX_STANDARD MATCHES "03") - message(STATUS "Compiling for C++98") + message(STATUS "Compiling for C++03") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 98) elseif (ETL_CXX_STANDARD MATCHES "11") message(STATUS "Compiling for C++11") @@ -32,9 +32,27 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() if (ETL_OPTIMISATION MATCHES "-O1") @@ -121,7 +139,3 @@ add_test(etl_error_handler_unit_tests etl_tests) # as they appear from UnitTest++ add_custom_target(test_verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose) - -#RSG -set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) - diff --git a/test/etl_error_handler/log_errors/test_error_handler.cpp b/test/etl_error_handler/log_errors/test_error_handler.cpp index 01381e36..61d35125 100644 --- a/test/etl_error_handler/log_errors/test_error_handler.cpp +++ b/test/etl_error_handler/log_errors/test_error_handler.cpp @@ -117,12 +117,12 @@ bool AssertFailAndReturnValue() return false; } +static ErrorLog error_log; + //***************************************************************************** int main() { - static ErrorLog error_log; - - etl::error_handler::set_callback(); + etl::error_handler::set_callback(error_log); Assert(false); Assert(true); diff --git a/test/etl_error_handler/log_errors_and_exceptions/CMakeLists.txt b/test/etl_error_handler/log_errors_and_exceptions/CMakeLists.txt index cad344d4..3a7100df 100644 --- a/test/etl_error_handler/log_errors_and_exceptions/CMakeLists.txt +++ b/test/etl_error_handler/log_errors_and_exceptions/CMakeLists.txt @@ -33,9 +33,27 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() if (ETL_OPTIMISATION MATCHES "-O1") @@ -120,7 +138,3 @@ add_test(etl_error_handler_unit_tests etl_tests) # as they appear from UnitTest++ add_custom_target(test_verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose) - -#RSG -set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) - diff --git a/test/etl_initializer_list/CMakeLists.txt b/test/etl_initializer_list/CMakeLists.txt index f29b5515..90437cdf 100644 --- a/test/etl_initializer_list/CMakeLists.txt +++ b/test/etl_initializer_list/CMakeLists.txt @@ -48,9 +48,27 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 26) + elseif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + else() + message(FATAL_ERROR "CMake version ${CMAKE_VERSION} is too old to support C++23 or C++26. Please upgrade to CMake 3.20 or later.") + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET etl_tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET etl_tests PROPERTY CXX_STANDARD 17) endif() target_include_directories(etl_tests diff --git a/test/run-coverage.sh b/test/run-coverage.sh index ef977f17..9266cd1b 100755 --- a/test/run-coverage.sh +++ b/test/run-coverage.sh @@ -44,7 +44,7 @@ mkdir -p "$BUILD" cd "$BUILD" || exit 1 touch total.info -for CXXSTD in 11 14 17 20 23; do +for CXXSTD in 11 14 17 20 23 26; do for NOSTL in OFF ON; do rm -rf CMakeFiles cmake -DEXTRA_COMPILE_OPTIONS="--coverage" \ @@ -76,6 +76,7 @@ for CXXSTD in 11 14 17 20 23; do done genhtml total.info --output-directory coverage --rc "genhtml_branch_coverage=1" --branch-coverage -t $COMPILER \ - --ignore-errors inconsistent + --ignore-errors inconsistent \ + --ignore-errors category cd .. diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index 18a65523..f2cc75e5 100755 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash clear echo -e @@ -47,7 +47,7 @@ PrintHelp() echo "$HelpColour" echo "----------------------------------------------------------------------------------" echo " Syntax : ./runtests.sh " - echo " C++ Standard : a, 03, 11, 14, 17, 20 or 23 (a = All standards) " + echo " C++ Standard : a, 03, 11, 14, 17, 20, 23 or 26 (a = All standards) " echo " Threads : Number of threads to use. Default = 4 " echo " Compiler select : gcc or clang. Default All compilers " echo "----------------------------------------------------------------------------------" @@ -101,6 +101,8 @@ elif [ "$1" = "20" ]; then requested_cxx_standard="20" elif [ "$1" = "23" ]; then requested_cxx_standard="23" +elif [ "$1" = "26" ]; then + requested_cxx_standard="26" elif [ "$1" = "A" ]; then requested_cxx_standard="All" elif [ "$1" = "a" ]; then @@ -288,8 +290,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -305,8 +307,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -533,8 +535,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -550,8 +552,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -777,8 +779,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -794,8 +796,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1021,8 +1023,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1038,8 +1040,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1265,8 +1267,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1282,8 +1284,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1509,8 +1511,8 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. -cmake --build bgcc +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang if [ $? -eq 0 ]; then PassedCompilation else @@ -1526,7 +1528,30 @@ PrintHeader rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang -CC=clang CXX=clang++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +fi + +############################################################################### +if [ "$requested_cxx_standard" = "26" ] || [ "$requested_cxx_standard" = "All" ]; then +SetCxxStandard "26" + +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. cmake --build bgcc if [ $? -eq 0 ]; then PassedCompilation @@ -1536,6 +1561,193 @@ else fi fi +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bgcc +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL - Force C++03" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bgcc +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL - Force C++03" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bgcc +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL - Force C++03" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL - Force C++03" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL - Built-in traits" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bgcc +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "gcc" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL - Built-in traits" +compiler=$gcc_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=gcc CXX=g++ cmake -E chdir bgcc cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bgcc +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "STL - Built-in traits" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + +if [ "$compiler_enabled" = "clang" ] || [ "$compiler_enabled" = "All compilers" ]; then +SetConfigurationName "No STL - Built-in traits" +compiler=$clang_compiler +PrintHeader +rm -rdf bgcc +rm -rdf bclang +cmake -E make_directory bgcc bclang +CC=clang CXX=clang++ cmake -E chdir bclang cmake -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=ON -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=$cxx_standard .. +cmake --build bclang +if [ $? -eq 0 ]; then + PassedCompilation +else + FailedCompilation + exit $? +fi +fi + fi ChecksCompleted diff --git a/test/run-tests.sh b/test/run-tests.sh index 06e39400..0381ac75 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -2,6 +2,8 @@ shopt -s xpg_echo +set -e + clear export ASAN_OPTIONS=symbol_line=1 @@ -54,7 +56,7 @@ PrintHelp() echo "$HelpColour" echo "----------------------------------------------------------------------------------------------------------" echo " Syntax : ./run-tests.sh " - echo " C++ Standard : 11, 14, 17, 20 or 23 " + echo " C++ Standard : 11, 14, 17, 20, 23, 26 or all " echo " Optimisation : 0, 1, 2 or 3. Default = 0 " echo " Threads : Number of threads to use. Default = 4 " echo " Sanitizer : s enables sanitizer checks, n disables. Default disabled " @@ -115,15 +117,19 @@ TestsCompleted() # Set the language standard. #****************************************************************************** if [ "$1" = "11" ]; then - cxx_standard="11" + cxx_standards="11" elif [ "$1" = "14" ]; then - cxx_standard="14" + cxx_standards="14" elif [ "$1" = "17" ]; then - cxx_standard="17" + cxx_standards="17" elif [ "$1" = "20" ]; then - cxx_standard="20" + cxx_standards="20" elif [ "$1" = "23" ]; then - cxx_standard="23" + cxx_standards="23" +elif [ "$1" = "26" ]; then + cxx_standards="26" +elif [ "$1" = "all" ]; then + cxx_standards="11 14 17 20 23 26" else PrintHelp exit @@ -180,10 +186,10 @@ fi #****************************************************************************** if [ "$6" = "v" ]; then verbose="On" - verbose_flag="-v" + verbose_cmake_flag="-DEXTRA_TESTING_FLAGS=-v" else verbose="Off" - verbose_flag="" + verbose_cmake_flag="" fi #****************************************************************************** @@ -196,66 +202,66 @@ etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r # Get the compiler versions #****************************************************************************** -while read i ; do - CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'` - MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'` - DIR=`echo $i | cut -d, -f3 | sed -e 's/ *$//'` - CMD=`echo $i | cut -d, -f4 | sed -e 's/ *$//'` +for cxx_standard in $cxx_standards ; do + while read i ; do + CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'` + MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'` + DIR=`echo $i | cut -d, -f3 | sed -e 's/ *$//'` + CMD=`echo $i | cut -d, -f4 | sed -e 's/ *$//'` - if [ "$compiler_enabled" = "$CC" ] || [ "$compiler_enabled" = "All compilers" ]; then - if [ "$CC" = "gcc" ] ; then - compiler=$(g++ --version | grep g++) - else - compiler=$(clang++ --version | grep clang) + if [ "$compiler_enabled" = "$CC" ] || [ "$compiler_enabled" = "All compilers" ]; then + if [ "$CC" = "gcc" ] ; then + compiler=$(g++ --version | grep g++) + else + compiler=$(clang++ --version | grep clang) + fi + OLD_DIR=`pwd` + cd $DIR + mkdir -p build-make || exit 1 + cd build-make || exit 1 + echo "ETL Tests" > log.txt + SetConfigurationName "$MSG" + PrintHeader + $CMD + if cmake --build .; then + PassedCompilation + else + FailedCompilation + exit 1 + fi + if ctest -V; then + PassedTests + else + FailedTests + exit 1 + fi + cd .. + rm -rf build-make + cd $OLD_DIR fi - OLD_DIR=`pwd` - cd $DIR - mkdir -p build-make || exit 1 - cd build-make || exit 1 - echo "ETL Tests" > log.txt - SetConfigurationName "$MSG" - PrintHeader - $CMD - cmake --build . - if [ $? -eq 0 ]; then - PassedCompilation - else - FailedCompilation - exit $? - fi - ./etl_tests $verbose_flag - if [ $? -eq 0 ]; then - PassedTests - else - FailedTests - exit $? - fi - cd .. - rm -rf build-make - cd $OLD_DIR - fi -done <<-EOF -gcc ,STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -gcc ,STL - Non-virtual messages,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=ON .. -gcc ,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -gcc ,No STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -gcc ,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -gcc ,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON .. -clang,STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -clang,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -clang,No STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -clang,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF .. -clang,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON .. -gcc ,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -clang,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -gcc ,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -gcc ,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -gcc ,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -gcc ,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -clang,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -clang,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -clang,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. -clang,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize .. + done <<-EOF +gcc ,STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +gcc ,STL - Non-virtual messages,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=ON $verbose_cmake_flag .. +gcc ,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +gcc ,No STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +gcc ,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +gcc ,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON $verbose_cmake_flag .. +clang,STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +clang,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +clang,No STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +clang,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag .. +clang,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON $verbose_cmake_flag .. +gcc ,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +clang,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +gcc ,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +gcc ,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +gcc ,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +gcc ,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +clang,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +clang,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +clang,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. +clang,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag .. EOF +done TestsCompleted diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 0e2627df..a7e87697 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -74,9 +74,25 @@ elseif (ETL_CXX_STANDARD MATCHES "17") elseif (ETL_CXX_STANDARD MATCHES "20") message(STATUS "Compiling for C++20") set_property(TARGET tests PROPERTY CXX_STANDARD 20) +elseif (ETL_CXX_STANDARD MATCHES "23") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") + message(STATUS "Compiling for C++23") + set_property(TARGET tests PROPERTY CXX_STANDARD 23) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++23, falling back to C++20") + set_property(TARGET tests PROPERTY CXX_STANDARD 20) + endif() +elseif (ETL_CXX_STANDARD MATCHES "26") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + message(STATUS "Compiling for C++26") + set_property(TARGET tests PROPERTY CXX_STANDARD 26) + else() + message(STATUS "CMake version ${CMAKE_VERSION} does not support C++26, falling back to C++23") + set_property(TARGET tests PROPERTY CXX_STANDARD 23) + endif() else() - message(STATUS "Compiling for C++23") - set_property(TARGET tests PROPERTY CXX_STANDARD 23) + message(STATUS "Compiling for C++17") + set_property(TARGET tests PROPERTY CXX_STANDARD 17) endif() target_sources(tests PRIVATE @@ -115,6 +131,10 @@ target_sources(tests PRIVATE checksum.h.t.cpp chrono.h.t.cpp concepts.h.t.cpp + const_map.h.t.cpp + const_multimap.h.t.cpp + const_multiset.h.t.cpp + const_set.h.t.cpp circular_buffer.h.t.cpp circular_iterator.h.t.cpp closure.h.t.cpp @@ -163,6 +183,7 @@ target_sources(tests PRIVATE crc32_q.h.t.cpp crc32_xfer.h.t.cpp crc64_ecma.h.t.cpp + crc64_iso.h.t.cpp crc8_ccitt.h.t.cpp crc8_cdma2000.h.t.cpp crc8_darc.h.t.cpp @@ -174,6 +195,7 @@ target_sources(tests PRIVATE crc8_j1850_zero.h.t.cpp crc8_maxim.h.t.cpp crc8_opensafety.h.t.cpp + crc8_nrsc5.h.t.cpp crc8_rohc.h.t.cpp crc8_wcdma.h.t.cpp cyclic_value.h.t.cpp @@ -215,6 +237,7 @@ target_sources(tests PRIVATE histogram.h.t.cpp ihash.h.t.cpp imemory_block_allocator.h.t.cpp + index_of_type.h.t.cpp indirect_vector.h.t.cpp initializer_list.h.t.cpp inplace_function.h.t.cpp @@ -239,6 +262,7 @@ target_sources(tests PRIVATE list.h.t.cpp log.h.t.cpp macros.h.t.cpp + manchester.h.t.cpp map.h.t.cpp math.h.t.cpp math_constants.h.t.cpp @@ -284,6 +308,7 @@ target_sources(tests PRIVATE poly_span.h.t.cpp pool.h.t.cpp power.h.t.cpp + print.h.t.cpp priority_queue.h.t.cpp pseudo_moving_average.h.t.cpp quantize.h.t.cpp @@ -295,6 +320,7 @@ target_sources(tests PRIVATE queue_spsc_locked.h.t.cpp radix.h.t.cpp random.h.t.cpp + ranges.h.t.cpp ratio.h.t.cpp reference_counted_message.h.t.cpp reference_counted_message_pool.h.t.cpp @@ -306,6 +332,7 @@ target_sources(tests PRIVATE rescale.h.t.cpp result.h.t.cpp rms.h.t.cpp + rounded_integral_division.h.t.cpp scaled_rounding.h.t.cpp scheduler.h.t.cpp set.h.t.cpp @@ -337,6 +364,7 @@ target_sources(tests PRIVATE to_wstring.h.t.cpp tuple.h.t.cpp type_def.h.t.cpp + type_list.h.t.cpp type_lookup.h.t.cpp type_select.h.t.cpp type_traits.h.t.cpp diff --git a/test/syntax_check/const_map.h.t.cpp b/test/syntax_check/const_map.h.t.cpp new file mode 100644 index 00000000..db4a753c --- /dev/null +++ b/test/syntax_check/const_map.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/const_multimap.h.t.cpp b/test/syntax_check/const_multimap.h.t.cpp new file mode 100644 index 00000000..da38716c --- /dev/null +++ b/test/syntax_check/const_multimap.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/const_multiset.h.t.cpp b/test/syntax_check/const_multiset.h.t.cpp new file mode 100644 index 00000000..12b01a8a --- /dev/null +++ b/test/syntax_check/const_multiset.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/const_set.h.t.cpp b/test/syntax_check/const_set.h.t.cpp new file mode 100644 index 00000000..1b73c9af --- /dev/null +++ b/test/syntax_check/const_set.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/crc64_iso.h.t.cpp b/test/syntax_check/crc64_iso.h.t.cpp new file mode 100644 index 00000000..a78f5430 --- /dev/null +++ b/test/syntax_check/crc64_iso.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/crc8_nrsc5.h.t.cpp b/test/syntax_check/crc8_nrsc5.h.t.cpp new file mode 100644 index 00000000..4dc725dd --- /dev/null +++ b/test/syntax_check/crc8_nrsc5.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/etl_profile.h b/test/syntax_check/etl_profile.h index ed633219..deee267c 100644 --- a/test/syntax_check/etl_profile.h +++ b/test/syntax_check/etl_profile.h @@ -31,7 +31,6 @@ SOFTWARE. #define ETL_TARGET_DEVICE_GENERIC #define ETL_TARGET_OS_NONE -#define ETL_IN_UNIT_TEST #define ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK #define ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS #define ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS diff --git a/test/syntax_check/index_of_type.h.t.cpp b/test/syntax_check/index_of_type.h.t.cpp new file mode 100644 index 00000000..0e854960 --- /dev/null +++ b/test/syntax_check/index_of_type.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/manchester.h.t.cpp b/test/syntax_check/manchester.h.t.cpp new file mode 100644 index 00000000..4e86c4f1 --- /dev/null +++ b/test/syntax_check/manchester.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/print.h.t.cpp b/test/syntax_check/print.h.t.cpp new file mode 100644 index 00000000..4fe9432b --- /dev/null +++ b/test/syntax_check/print.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/ranges.h.t.cpp b/test/syntax_check/ranges.h.t.cpp new file mode 100644 index 00000000..41861be9 --- /dev/null +++ b/test/syntax_check/ranges.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/rounded_integral_division.h.t.cpp b/test/syntax_check/rounded_integral_division.h.t.cpp new file mode 100644 index 00000000..4c2ea104 --- /dev/null +++ b/test/syntax_check/rounded_integral_division.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/type_list.h.t.cpp b/test/syntax_check/type_list.h.t.cpp new file mode 100644 index 00000000..d8fd1469 --- /dev/null +++ b/test/syntax_check/type_list.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index fa0f4f0e..abc5f734 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -2621,8 +2621,10 @@ namespace for (size_t i = 0UL; i <= initial_data.size(); ++i) { +#include "etl/private/diagnostic_null_dereference_push.h" std::vector data1(initial_data); std::vector data2(initial_data); +#include "etl/private/diagnostic_pop.h" auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size()); auto etl_result = etl::rotate(data2.data(), data2.data() + i, data2.data() + data2.size()); @@ -2658,8 +2660,10 @@ namespace for (size_t i = 0UL; i <= initial_data.size(); ++i) { +#include "etl/private/diagnostic_null_dereference_push.h" std::vector data1(initial_data); std::vector data2(initial_data); +#include "etl/private/diagnostic_pop.h" auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size()); diff --git a/test/test_atomic.cpp b/test/test_atomic.cpp index 2128332b..9870caf8 100644 --- a/test/test_atomic.cpp +++ b/test/test_atomic.cpp @@ -488,6 +488,72 @@ namespace CHECK_EQUAL(compare.fetch_xor(0x55AA55AAUL), test.fetch_xor(0x55AA55AAUL)); } + //************************************************************************* + TEST(test_atomic_operator_fetch_max_when_new_value_is_greater) + { + etl::atomic test(10); + + int old_value = test.fetch_max(20); + + CHECK_EQUAL(10, old_value); + CHECK_EQUAL(20, test.load()); + } + + //************************************************************************* + TEST(test_atomic_operator_fetch_max_when_new_value_is_less) + { + etl::atomic test(30); + + int old_value = test.fetch_max(20); + + CHECK_EQUAL(30, old_value); + CHECK_EQUAL(30, test.load()); + } + + //************************************************************************* + TEST(test_atomic_operator_fetch_max_when_new_value_is_equal) + { + etl::atomic test(20); + + int old_value = test.fetch_max(20); + + CHECK_EQUAL(20, old_value); + CHECK_EQUAL(20, test.load()); + } + + //************************************************************************* + TEST(test_atomic_operator_fetch_min_when_new_value_is_less) + { + etl::atomic test(30); + + int old_value = test.fetch_min(20); + + CHECK_EQUAL(30, old_value); + CHECK_EQUAL(20, test.load()); + } + + //************************************************************************* + TEST(test_atomic_operator_fetch_min_when_new_value_is_greater) + { + etl::atomic test(10); + + int old_value = test.fetch_min(20); + + CHECK_EQUAL(10, old_value); + CHECK_EQUAL(10, test.load()); + } + + //************************************************************************* + TEST(test_atomic_operator_fetch_min_when_new_value_is_equal) + { + etl::atomic test(20); + + int old_value = test.fetch_min(20); + + CHECK_EQUAL(20, old_value); + CHECK_EQUAL(20, test.load()); + } + //************************************************************************* TEST(test_atomic_integer_exchange) { diff --git a/test/test_bit_stream.cpp b/test/test_bit_stream.cpp index 2c515224..d7e1cdbc 100644 --- a/test/test_bit_stream.cpp +++ b/test/test_bit_stream.cpp @@ -869,7 +869,7 @@ namespace TEST(put_get_multiple_full_size) { char c1 = 90; - char c2 = -91; + char c2 = static_cast(-91); unsigned short s1 = 23205; unsigned short s2 = 42330; int32_t i1 = 1520786085L; // 0x5AA55AA5 diff --git a/test/test_bit_stream_writer_big_endian.cpp b/test/test_bit_stream_writer_big_endian.cpp index 893a5f04..c22e66db 100644 --- a/test/test_bit_stream_writer_big_endian.cpp +++ b/test/test_bit_stream_writer_big_endian.cpp @@ -614,7 +614,7 @@ namespace TEST(test_write_multiple_full_size) { char c1 = 90; // 0x5A - char c2 = -91; // 0xA5 + char c2 = static_cast(-91); // 0xA5 unsigned short s1 = 4660; // 0x1234 unsigned short s2 = 22136; // 0x5678 int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF @@ -660,7 +660,7 @@ namespace TEST(test_write_multiple_variable_size) { char c1 = 90; // 0x5A 6 bits - char c2 = -91; // 0xA5 7 bits + char c2 = static_cast(-91); // 0xA5 7 bits unsigned short s1 = 4660; // 0x1234 13 bits unsigned short s2 = 22136; // 0x5678 11 bits int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF 23 bits @@ -705,7 +705,7 @@ namespace Accumulator accumulator; char c1 = 90; // 0x5A 6 bits - char c2 = -91; // 0xA5 7 bits + char c2 = static_cast(-91); // 0xA5 7 bits unsigned short s1 = 4660U; // 0x1234 13 bits unsigned short s2 = 22136U; // 0x5678 11 bits int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF 23 bits diff --git a/test/test_bit_stream_writer_little_endian.cpp b/test/test_bit_stream_writer_little_endian.cpp index 1d6f85d5..07348253 100644 --- a/test/test_bit_stream_writer_little_endian.cpp +++ b/test/test_bit_stream_writer_little_endian.cpp @@ -702,7 +702,7 @@ namespace TEST(test_write_multiple_full_size) { char c1 = 90; // 0x5A - char c2 = -91; // 0xA5 + char c2 = static_cast(-91); // 0xA5 unsigned short s1 = 4660; // 0x1234 unsigned short s2 = 22136; // 0x5678 int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF @@ -748,7 +748,7 @@ namespace TEST(test_write_multiple_variable_size) { char c1 = 90; // 0x5A 6 bits - char c2 = -91; // 0xA5 7 bits + char c2 = static_cast(-91); // 0xA5 7 bits unsigned short s1 = 4660; // 0x1234 13 bits unsigned short s2 = 22136; // 0x5678 11 bits int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF 23 bits @@ -791,7 +791,7 @@ namespace TEST(test_write_multiple_variable_size_with_callback) { char c1 = 90; // 0x5A 6 bits - char c2 = -91; // 0xA5 7 bits + char c2 = static_cast(-91); // 0xA5 7 bits unsigned short s1 = 4660; // 0x1234 13 bits unsigned short s2 = 22136; // 0x5678 11 bits int32_t i1 = static_cast(0x89ABCDEFU); // 0x89ABCDEF 23 bits diff --git a/test/test_byte_stream.cpp b/test/test_byte_stream.cpp index 29570ac1..06b2a453 100644 --- a/test/test_byte_stream.cpp +++ b/test/test_byte_stream.cpp @@ -1026,7 +1026,7 @@ namespace TEST(write_read_multiple_big_endian) { char c1 = 90; - char c2 = -91; + char c2 = static_cast(-91); unsigned short s1 = 23205; unsigned short s2 = 42330; int32_t i1 = 1520786085; // 0x5AA55AA5 @@ -1089,7 +1089,7 @@ namespace TEST(write_read_multiple_little_endian) { char c1 = 90; - char c2 = -91; + char c2 = static_cast(-91); unsigned short s1 = 23205; unsigned short s2 = 42330; int32_t i1 = 1520786085; // 0x5AA55AA5 diff --git a/test/test_chrono_year_month_weekday.cpp b/test/test_chrono_year_month_weekday.cpp index 8079d813..f0ab8500 100644 --- a/test/test_chrono_year_month_weekday.cpp +++ b/test/test_chrono_year_month_weekday.cpp @@ -117,10 +117,30 @@ namespace //************************************************************************* TEST(test_to_sys_days) { - Chrono::year_month_weekday ymwd{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)}; - Chrono::sys_days sd = Chrono::sys_days(ymwd); + // 1st Thursday of February 2000 (Feb 3) + Chrono::year_month_weekday ymwd1{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)}; + Chrono::sys_days sd1 = Chrono::sys_days(ymwd1); + CHECK_EQUAL(10990, sd1.time_since_epoch().count()); - CHECK_EQUAL(10990, sd.time_since_epoch().count()); + // 2nd Wednesday of March 2000 (Mar 8) + Chrono::year_month_weekday ymwd2{Chrono::year(2000), Chrono::March, Chrono::weekday_indexed(Chrono::Wednesday, 2)}; + Chrono::sys_days sd2 = Chrono::sys_days(ymwd2); + CHECK_EQUAL(11024, sd2.time_since_epoch().count()); + + // 1st Sunday of January 2000 (Jan 2) + Chrono::year_month_weekday ymwd3{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Sunday, 1)}; + Chrono::sys_days sd3 = Chrono::sys_days(ymwd3); + CHECK_EQUAL(10958, sd3.time_since_epoch().count()); + + // 3rd Friday of June 1985 (Jun 21) + Chrono::year_month_weekday ymwd4{Chrono::year(1985), Chrono::June, Chrono::weekday_indexed(Chrono::Friday, 3)}; + Chrono::sys_days sd4 = Chrono::sys_days(ymwd4); + CHECK_EQUAL(5650, sd4.time_since_epoch().count()); + + // 2nd Wednesday of March 2024 (Mar 13) + Chrono::year_month_weekday ymwd5{Chrono::year(2024), Chrono::March, Chrono::weekday_indexed(Chrono::Wednesday, 2)}; + Chrono::sys_days sd5 = Chrono::sys_days(ymwd5); + CHECK_EQUAL(19795, sd5.time_since_epoch().count()); } //************************************************************************* diff --git a/test/test_chrono_year_month_weekday_last.cpp b/test/test_chrono_year_month_weekday_last.cpp index 7050903f..bbe92619 100644 --- a/test/test_chrono_year_month_weekday_last.cpp +++ b/test/test_chrono_year_month_weekday_last.cpp @@ -73,7 +73,7 @@ namespace Chrono::year_month_weekday_last ymwdl{Chrono::year(2000), Chrono::February, Chrono::weekday_last(Chrono::Thursday)}; Chrono::sys_days sd = Chrono::sys_days(ymwdl); - CHECK_EQUAL(11012, sd.time_since_epoch().count()); + CHECK_EQUAL(11011, sd.time_since_epoch().count()); } //************************************************************************* diff --git a/test/test_closure.cpp b/test/test_closure_with_default_delegate.cpp similarity index 99% rename from test/test_closure.cpp rename to test/test_closure_with_default_delegate.cpp index 3e01ca8b..a7ef4f35 100644 --- a/test/test_closure.cpp +++ b/test/test_closure_with_default_delegate.cpp @@ -34,7 +34,7 @@ SOFTWARE. namespace { - SUITE(test_closure) + SUITE(test_closure_with_default_delegate) { int f1(int a1) { diff --git a/test/test_closure_constexpr.cpp b/test/test_closure_with_default_delegate_constexpr.cpp similarity index 99% rename from test/test_closure_constexpr.cpp rename to test/test_closure_with_default_delegate_constexpr.cpp index 73c4b68c..57dcc18d 100644 --- a/test/test_closure_constexpr.cpp +++ b/test/test_closure_with_default_delegate_constexpr.cpp @@ -34,7 +34,7 @@ SOFTWARE. namespace { - SUITE(test_closure) + SUITE(test_closure_with_default_delegate_constexpr) { static constexpr int f1(int a1) { diff --git a/test/test_closure_with_inplace_function.cpp b/test/test_closure_with_inplace_function.cpp new file mode 100644 index 00000000..cd67ffba --- /dev/null +++ b/test/test_closure_with_inplace_function.cpp @@ -0,0 +1,208 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG, John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/closure.h" +#include "etl/inplace_function.h" + +#include + +namespace +{ + SUITE(test_closure_with_inplace_function) + { + int f1(int a1) + { + return a1 * 3; + } + + int f1_throwing(int) + { + throw std::runtime_error("throwing function"); + } + + void f1_void(int) {} + + int f1_ref(int& a1) + { + return a1 * 3; + } + + int f2(int a1, int a2) + { + return a1 * 3 + a2; + } + + int f3(int a1, int a2, int a3) + { + return a1 * 3 + a2 * a3; + } + + int f4(int a1, int a2, int a3, int a4) + { + return a1 * 3 + a2 * a3 + a4; + } + + int f5(int a1, int a2, int a3, int a4, int a5) + { + return a1 * 3 + a2 * a3 + a4 * a5; + } + + using f1_type = int(int); + using f1_ref_type = int(int&); + using f1_void_type = void(int); + using f2_type = int(int, int); + using f3_type = int(int, int, int); + using f4_type = int(int, int, int, int); + using f5_type = int(int, int, int, int, int); + + using ipf1_type = etl::inplace_function; + using ipf1_ref_type = etl::inplace_function; + using ipf1_void_type = etl::inplace_function; + using ipf2_type = etl::inplace_function; + using ipf3_type = etl::inplace_function; + using ipf4_type = etl::inplace_function; + using ipf5_type = etl::inplace_function; + + ipf1_type ipf1 = ipf1_type::create<&f1>(); + ipf1_type ipf1_throwing = ipf1_type::create<&f1_throwing>(); + ipf1_ref_type ipf1_ref = ipf1_ref_type::create<&f1_ref>(); + ipf1_void_type ipf1_void = ipf1_void_type::create<&f1_void>(); + ipf2_type ipf2 = ipf2_type::create<&f2>(); + ipf3_type ipf3 = ipf3_type::create<&f3>(); + ipf4_type ipf4 = ipf4_type::create<&f4>(); + ipf5_type ipf5 = ipf5_type::create<&f5>(); + + //************************************************************************* + TEST(test_1_arg) + { + etl::closure c1(ipf1, 4); + CHECK_EQUAL(12, c1()); + } + + //************************************************************************* + TEST(test_1_arg_reference) + { + int v1 = 4; + etl::closure c1_ref(ipf1_ref, v1); + CHECK_EQUAL(12, c1_ref()); + v1 = 5; + CHECK_EQUAL(15, c1_ref()); + } + + //************************************************************************* + TEST(test_1_arg_lambda) + { + auto l = [](int a) + { + return a + 11; + }; + ipf1_type ipf1_lambda(l); + + etl::closure c1_lambda(ipf1_lambda, 5); + CHECK_EQUAL(16, c1_lambda()); + } + + //************************************************************************* + TEST(test_throwing) + { + etl::closure c1(ipf1_throwing, 4); + CHECK_THROW(c1(), std::runtime_error); + } + + //************************************************************************* + TEST(test_void) + { + etl::closure c1(ipf1_void, 4); + c1(); + } + + //************************************************************************* + TEST(test_2_args) + { + etl::closure c2(ipf2, 4, 3); + CHECK_EQUAL(15, c2()); + } + +#if ETL_USING_CPP11 && !defined(ETL_CLOSURE_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************* + TEST(test_2_args_bind) + { + etl::closure c2(ipf2, 4, 3); + CHECK_EQUAL(15, c2()); + + c2.bind<0>(7); + c2.bind<1>(8); + CHECK_EQUAL(29, c2()); + } + + //************************************************************************* + TEST(test_2_args_bind_all) + { + etl::closure c2(ipf2, 4, 3); + CHECK_EQUAL(15, c2()); + + c2.bind(7, 8); + CHECK_EQUAL(29, c2()); + } +#endif + + //************************************************************************* + TEST(test_3_args) + { + etl::closure c3(ipf3, 4, 3, 2); + CHECK_EQUAL(18, c3()); + } + + //************************************************************************* + TEST(test_4_args) + { + etl::closure c4(ipf4, 4, 3, 2, 1); + CHECK_EQUAL(19, c4()); + } + + //************************************************************************* + TEST(test_5_args) + { + etl::closure c5(ipf5, 4, 3, 2, 1, 5); + CHECK_EQUAL(23, c5()); + } + + //************************************************************************* + TEST(test_bind_static_assert) + { + etl::closure c(ipf2, 1, 2); + + // Uncomment to generate static_assert errors. + // c.bind(1); // Argument count mismatch + // c.bind(1, 2, 3); // Argument count mismatch + // c.bind(1, std::string()); // Argument is not convertible + } + } +} // namespace diff --git a/test/test_delegate.cpp b/test/test_delegate.cpp index b8445166..d57ad1f8 100644 --- a/test/test_delegate.cpp +++ b/test/test_delegate.cpp @@ -372,6 +372,27 @@ namespace CHECK_FALSE(d.is_valid()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_after_init_empty_braces) + { + etl::delegate d = {}; + + CHECK_FALSE(d.is_valid()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_after_assign_empty_braces) + { + auto lambda = [] { + }; + + etl::delegate d(lambda); + + CHECK_TRUE(d.is_valid()); + d = {}; + CHECK_FALSE(d.is_valid()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_free_void) { diff --git a/test/test_etl_traits.cpp b/test/test_etl_traits.cpp index 3ddb93fa..a90f073c 100644 --- a/test/test_etl_traits.cpp +++ b/test/test_etl_traits.cpp @@ -49,6 +49,7 @@ namespace CHECK_EQUAL((ETL_USING_CPP17 == 1), etl::traits::using_cpp17); CHECK_EQUAL((ETL_USING_CPP20 == 1), etl::traits::using_cpp20); CHECK_EQUAL((ETL_USING_CPP23 == 1), etl::traits::using_cpp23); + CHECK_EQUAL((ETL_USING_CPP26 == 1), etl::traits::using_cpp26); CHECK_EQUAL((ETL_USING_EXCEPTIONS == 1), etl::traits::using_exceptions); CHECK_EQUAL((ETL_USING_LIBC_WCHAR_H == 1), etl::traits::using_libc_wchar_h); CHECK_EQUAL((ETL_USING_GCC_COMPILER == 1), etl::traits::using_gcc_compiler); @@ -92,7 +93,9 @@ namespace CHECK_EQUAL(ETL_VERSION_MINOR, etl::traits::version_minor); CHECK_EQUAL(ETL_VERSION_PATCH, etl::traits::version_patch); CHECK_EQUAL(ETL_VERSION_VALUE, etl::traits::version); -#if ETL_USING_CPP23 +#if ETL_USING_CPP26 + CHECK_EQUAL(26, etl::traits::language_standard); +#elif ETL_USING_CPP23 CHECK_EQUAL(23, etl::traits::language_standard); #elif ETL_USING_CPP20 CHECK_EQUAL(20, etl::traits::language_standard); diff --git a/test/test_format.cpp b/test/test_format.cpp index 591d83f1..1a5e1476 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -203,8 +203,8 @@ namespace etl::string<100> s; CHECK_EQUAL("1.0", test_format(s, "{}", 1.0f)); - CHECK_EQUAL("1.234567", test_format(s, "{}", 1.234567f)); - CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678f)); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345674f)); + CHECK_EQUAL("1.234568", test_format(s, "{}", 1.2345676f)); CHECK_EQUAL("1.125", test_format(s, "{}", 1.125f)); } @@ -214,8 +214,8 @@ namespace etl::string<100> s; CHECK_EQUAL("1.0", test_format(s, "{}", 1.0)); - CHECK_EQUAL("1.234564", test_format(s, "{}", 1.234564)); - CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678)); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.234567499)); + CHECK_EQUAL("1.234568", test_format(s, "{}", 1.234567501)); CHECK_EQUAL("1.5", test_format(s, "{}", 1.5)); } @@ -227,7 +227,7 @@ namespace CHECK_EQUAL("1.0", test_format(s, "{}", 1.0l)); auto& result = test_format(s, "{}", 1.234567l); CHECK("1.234567" == result || "1.234566" == result); - CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678l)); + CHECK_EQUAL("1.234568", test_format(s, "{}", 1.2345678l)); CHECK_EQUAL("1.25", test_format(s, "{}", 1.25l)); } @@ -261,11 +261,94 @@ namespace CHECK_EQUAL("inf", test_format(s, "{:g}", INFINITY)); CHECK_EQUAL("INF", test_format(s, "{:0.3G}", INFINITY)); CHECK_EQUAL("0x1.8p+0", test_format(s, "{:a}", 1.5f)); - CHECK_EQUAL("0X1.4CCCCCCCCCP+0", test_format(s, "{:A}", 1.3l)); + CHECK_EQUAL("0X1.4CCCCCCCCDP+0", test_format(s, "{:A}", 1.3l)); CHECK_EQUAL("0x2.49fp+4", test_format(s, "{:a}", 150000.0)); CHECK_EQUAL("0x1.92a738p-5", test_format(s, "{:a}", 0.0000015f)); CHECK_EQUAL("0x1.6345785d8ap+e", test_format(s, "{:a}", 100000000000000000.l)); } + + //************************************************************************* + TEST(test_format_negative_zero) + { + etl::string<100> s; + + // Test negative zero handling - signbit() correctly detects -0.0 + CHECK_EQUAL("-0.0", test_format(s, "{}", -0.0)); + CHECK_EQUAL("-0.0", test_format(s, "{}", -0.0f)); + CHECK_EQUAL("-0.0", test_format(s, "{}", -0.0L)); + CHECK_EQUAL("-0.000000", test_format(s, "{:f}", -0.0)); + CHECK_EQUAL("-0.000000", test_format(s, "{:f}", -0.0f)); + CHECK_EQUAL("-0.000000", test_format(s, "{:f}", -0.0L)); + CHECK_EQUAL("-0.000000e+00", test_format(s, "{:e}", -0.0)); + CHECK_EQUAL("-0.000000e+00", test_format(s, "{:e}", -0.0f)); + CHECK_EQUAL("-0.000000e+00", test_format(s, "{:e}", -0.0L)); + CHECK_EQUAL("-0x0.0p+0", test_format(s, "{:a}", -0.0)); + CHECK_EQUAL("-0x0.0p+0", test_format(s, "{:a}", -0.0f)); + CHECK_EQUAL("-0x0.0p+0", test_format(s, "{:a}", -0.0L)); + } + + //************************************************************************* + // Tests for fractional rounding carry: + // When round(fractional * scale) == scale the fractional part must wrap + // to 0 and the integral part must be incremented by 1. + //************************************************************************* + TEST(test_format_floating_default_rounding_carry) + { + etl::string<100> s; + + // 1.9999999: fractional 0.9999999, round(0.9999999 * 1e6) == 1000000 + // => must carry: integral 1 -> 2, fractional -> 0 + CHECK_EQUAL("2.0", test_format(s, "{}", 1.9999999)); + CHECK_EQUAL("-2.0", test_format(s, "{}", -1.9999999)); + + // 0.9999999: integral 0, fractional rounds up => becomes 1.0 + CHECK_EQUAL("1.0", test_format(s, "{}", 0.9999999)); + + // 99.9999999: integral 99, fractional rounds up => becomes 100.0 + CHECK_EQUAL("100.0", test_format(s, "{}", 99.9999999)); + } + + //************************************************************************* + TEST(test_format_floating_f_rounding_carry) + { + etl::string<100> s; + + // Same values using {:f} which uses format_floating_f (6 fractional decimals) + CHECK_EQUAL("2.000000", test_format(s, "{:f}", 1.9999999)); + CHECK_EQUAL("-2.000000", test_format(s, "{:f}", -1.9999999)); + CHECK_EQUAL("1.000000", test_format(s, "{:f}", 0.9999999)); + CHECK_EQUAL("100.000000", test_format(s, "{:f}", 99.9999999)); + } + + //************************************************************************* + TEST(test_format_floating_e_rounding_carry) + { + etl::string<100> s; + + // 9.9999999: after normalization integral=9, fractional=0.9999999 + // round(0.9999999 * 1e6) == 1000000 => must carry: 10.000000e+00 + CHECK_EQUAL("10.000000e+00", test_format(s, "{:e}", 9.9999999)); + CHECK_EQUAL("-10.000000e+00", test_format(s, "{:e}", -9.9999999)); + + // 1.9999999: after normalization integral=1, fractional=0.9999999 + CHECK_EQUAL("2.000000e+00", test_format(s, "{:e}", 1.9999999)); + } + + //************************************************************************* + TEST(test_format_floating_a_rounding_carry) + { + etl::string<100> s; + + // 1.5 + (1.0 - 2^-52) * 0.5 ≈ value whose hex fractional part rounds up. + // Use a value where hex fractional is all 0xF...F and rounds up. + // 2.0 - epsilon: in hex, 0x1.FFFFFFFFFFFFFp+0 (for double) + // After modf: integral=1, fractional ≈ 0.999... + // round(fractional * 16^10) should equal 16^10 => carry + double almost_two = 1.9999999999999998; // nextafter(2.0, 0.0) or very close + auto& result = test_format(s, "{:a}", almost_two); + // After carry, integral becomes 2, fractional becomes 0 + CHECK_EQUAL("0x2.0p+0", result); + } #endif //************************************************************************* diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 08337c28..02d928de 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -42,6 +42,7 @@ SOFTWARE. namespace { +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_forward_list) { const size_t SIZE = 10UL; @@ -1444,4 +1445,5 @@ namespace } #endif } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_forward_list_shared_pool.cpp b/test/test_forward_list_shared_pool.cpp index 701bfe44..996efe7a 100644 --- a/test/test_forward_list_shared_pool.cpp +++ b/test/test_forward_list_shared_pool.cpp @@ -42,6 +42,7 @@ SOFTWARE. namespace { +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_forward_list) { const size_t SIZE = 20UL; @@ -1929,4 +1930,5 @@ namespace CHECK(data3 > data1); } } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_hash.cpp b/test/test_hash.cpp index 73a616f8..d1acd6b1 100644 --- a/test/test_hash.cpp +++ b/test/test_hash.cpp @@ -149,7 +149,14 @@ namespace if (ETL_PLATFORM_32BIT) { - CHECK_EQUAL(0xEC6A8D69UL, hash); + if (etl::endianness::value() == etl::endian::little) + { + CHECK_EQUAL(0xEC6A8D69UL, hash); + } + else + { + CHECK_EQUAL(0x5F69FD19UL, hash); + } } if (ETL_PLATFORM_64BIT) @@ -165,7 +172,14 @@ namespace if (ETL_PLATFORM_32BIT) { - CHECK_EQUAL(0xEC6A8D69UL, hash); + if (etl::endianness::value() == etl::endian::little) + { + CHECK_EQUAL(0xEC6A8D69UL, hash); + } + else + { + CHECK_EQUAL(0x5F69FD19UL, hash); + } } if (ETL_PLATFORM_64BIT) @@ -177,7 +191,7 @@ namespace //************************************************************************* TEST(test_hash_float) { - size_t hash = etl::hash()((float)(1.2345)); + size_t hash = etl::hash()(1.2345f); if (ETL_PLATFORM_32BIT) { @@ -204,7 +218,14 @@ namespace if (ETL_PLATFORM_32BIT) { - CHECK_EQUAL(0x86FBF224UL, hash); + if (etl::endianness::value() == etl::endian::little) + { + CHECK_EQUAL(0x86FBF224UL, hash); + } + else + { + CHECK_EQUAL(0xD1F372DEUL, hash); + } } if (ETL_PLATFORM_64BIT) diff --git a/test/test_histogram.cpp b/test/test_histogram.cpp index 92857deb..a68970f9 100644 --- a/test/test_histogram.cpp +++ b/test/test_histogram.cpp @@ -166,7 +166,7 @@ namespace for (size_t i = 0UL; i < output1.size(); ++i) { - CHECK_EQUAL(int(output1[i]), int(histogram[i])); + CHECK_EQUAL(static_cast(output1[i]), static_cast(histogram[static_cast(i)])); } } @@ -203,7 +203,7 @@ namespace for (size_t i = 0UL; i < output1.size(); ++i) { - CHECK_EQUAL(int(output1[i]), int(histogram[i - 4])); + CHECK_EQUAL(static_cast(output1[i]), static_cast(histogram[static_cast(i) - 4])); } } diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index 33002fd7..5be470bc 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -129,6 +129,7 @@ namespace namespace { +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_intrusive_forward_list) { InitialDataNDC stable_sort_data; @@ -1379,4 +1380,5 @@ namespace CHECK_FALSE(data0.contains(compare_node2)); } } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index 0c352b5d..4b2f6f85 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -142,6 +142,7 @@ namespace namespace { +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_intrusive_list) { InitialDataNDC stable_sort_data; @@ -1648,4 +1649,5 @@ namespace CHECK_FALSE(data0.contains(compare_node2)); } } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_manchester.cpp b/test/test_manchester.cpp index bd357435..a69bfdb5 100644 --- a/test/test_manchester.cpp +++ b/test/test_manchester.cpp @@ -1,3 +1,31 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2026 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + #include "etl/manchester.h" #include "unit_test_framework.h" diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 9513e778..eeddc426 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -47,6 +47,64 @@ SOFTWARE. #include #include +//*************************************************************************** +/// A non-trivially-relocatable type that tracks moves and destructions. +/// Used to exercise the manual move-and-destroy path of etl::relocate. +//*************************************************************************** +struct relocatable_t +{ + int value; + bool was_moved_into; ///< true when this object was constructed via move + + static int destructor_count; + + static void reset_counts() + { + destructor_count = 0; + } + + explicit relocatable_t(int v = 0) + : value(v) + , was_moved_into(false) + { + } + + relocatable_t(relocatable_t&& other) ETL_NOEXCEPT + : value(other.value) + , was_moved_into(true) + { + other.value = -1; // mark source as moved-from + } + + ~relocatable_t() + { + ++destructor_count; + } + + // Non-copyable to make the intent clear. + relocatable_t(const relocatable_t&) = delete; + relocatable_t& operator=(const relocatable_t&) = delete; + relocatable_t& operator=(relocatable_t&&) = delete; +}; + +int relocatable_t::destructor_count = 0; + +// In configurations where etl::is_nothrow_relocatable is a class template +// (non-STL builds), we must provide an explicit specialisation so that +// etl::relocate is enabled for relocatable_t. When the STL is available the +// trait is a type alias that already evaluates to true for types with a +// nothrow move constructor and a nothrow destructor, so no specialisation is +// needed (or even possible). +#if !(ETL_USING_STL && ETL_USING_CPP11) +namespace etl +{ + template <> + struct is_nothrow_relocatable : public etl::true_type + { + }; +} // namespace etl +#endif + namespace { typedef std::string non_trivial_t; @@ -2660,5 +2718,267 @@ namespace CHECK(result == p); } #endif + +#if ETL_USING_CPP11 + //************************************************************************* + TEST(test_trivially_relocate_trivial) + { + alignas(trivial_t) unsigned char src_buffer[sizeof(trivial_t) * SIZE]; + alignas(trivial_t) unsigned char dst_buffer[sizeof(trivial_t) * SIZE]; + + trivial_t* src = reinterpret_cast(src_buffer); + trivial_t* dst = reinterpret_cast(dst_buffer); + + // Initialize source + for (size_t i = 0; i < SIZE; ++i) + { + src[i] = test_data_trivial[i]; + } + + // Relocate + trivial_t* result = etl::trivially_relocate(src, src + SIZE, dst); + + // Check result + CHECK(result == dst + SIZE); + + // Check destination values + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_EQUAL(test_data_trivial[i], dst[i]); + } + } + + //************************************************************************* + TEST(test_trivially_relocate_same_location) + { + alignas(trivial_t) unsigned char buffer[sizeof(trivial_t) * SIZE]; + trivial_t* p = reinterpret_cast(buffer); + + // Initialize + for (size_t i = 0; i < SIZE; ++i) + { + p[i] = test_data_trivial[i]; + } + + // Relocate to same location should return last + trivial_t* result = etl::trivially_relocate(p, p + SIZE, p); + + CHECK(result == p + SIZE); + + // Values should be unchanged + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_EQUAL(test_data_trivial[i], p[i]); + } + } + + //************************************************************************* + TEST(test_trivially_relocate_empty_range) + { + alignas(trivial_t) unsigned char src_buffer[sizeof(trivial_t) * SIZE]; + alignas(trivial_t) unsigned char dst_buffer[sizeof(trivial_t) * SIZE]; + + trivial_t* src = reinterpret_cast(src_buffer); + trivial_t* dst = reinterpret_cast(dst_buffer); + + // Relocate empty range + trivial_t* result = etl::trivially_relocate(src, src, dst); + + CHECK(result == dst); + } + + //************************************************************************* + TEST(test_trivially_relocate_overlapping_forward) + { + alignas(trivial_t) unsigned char buffer[sizeof(trivial_t) * (SIZE + 2)]; + trivial_t* p = reinterpret_cast(buffer); + + // Initialize + for (size_t i = 0; i < SIZE; ++i) + { + p[i] = test_data_trivial[i]; + } + + // Relocate forward (overlapping) - shift elements by 2 + trivial_t* result = etl::trivially_relocate(p, p + SIZE, p + 2); + + CHECK(result == p + SIZE + 2); + + // Check values + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_EQUAL(test_data_trivial[i], p[i + 2]); + } + } + + //************************************************************************* + TEST(test_relocate_trivial) + { + alignas(trivial_t) unsigned char src_buffer[sizeof(trivial_t) * SIZE]; + alignas(trivial_t) unsigned char dst_buffer[sizeof(trivial_t) * SIZE]; + + trivial_t* src = reinterpret_cast(src_buffer); + trivial_t* dst = reinterpret_cast(dst_buffer); + + // Initialize source + for (size_t i = 0; i < SIZE; ++i) + { + src[i] = test_data_trivial[i]; + } + + // Relocate + trivial_t* result = etl::relocate(src, src + SIZE, dst); + + // Check result + CHECK(result == dst + SIZE); + + // Check destination values + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_EQUAL(test_data_trivial[i], dst[i]); + } + } + + //************************************************************************* + TEST(test_relocate_same_location) + { + alignas(trivial_t) unsigned char buffer[sizeof(trivial_t) * SIZE]; + trivial_t* p = reinterpret_cast(buffer); + + // Initialize + for (size_t i = 0; i < SIZE; ++i) + { + p[i] = test_data_trivial[i]; + } + + // Relocate to same location should return last + trivial_t* result = etl::relocate(p, p + SIZE, p); + + CHECK(result == p + SIZE); + + // Values should be unchanged + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_EQUAL(test_data_trivial[i], p[i]); + } + } + + //************************************************************************* + TEST(test_relocate_empty_range) + { + alignas(trivial_t) unsigned char src_buffer[sizeof(trivial_t) * SIZE]; + alignas(trivial_t) unsigned char dst_buffer[sizeof(trivial_t) * SIZE]; + + trivial_t* src = reinterpret_cast(src_buffer); + trivial_t* dst = reinterpret_cast(dst_buffer); + + // Relocate empty range + trivial_t* result = etl::relocate(src, src, dst); + + CHECK(result == dst); + } + + //************************************************************************* + TEST(test_relocate_non_trivial) + { + const size_t N = 5; + + alignas(relocatable_t) unsigned char src_buffer[sizeof(relocatable_t) * N]; + alignas(relocatable_t) unsigned char dst_buffer[sizeof(relocatable_t) * N]; + + relocatable_t* src = reinterpret_cast(src_buffer); + relocatable_t* dst = reinterpret_cast(dst_buffer); + + // Placement-new source objects + for (size_t i = 0; i < N; ++i) + { + ::new (static_cast(src + i)) relocatable_t(static_cast(i + 1)); + } + + relocatable_t::reset_counts(); + + // Relocate (non-trivial path: move-construct into dst, destroy src) + relocatable_t* result = etl::relocate(src, src + N, dst); + + // Returned pointer must be one-past-end of destination + CHECK(result == dst + N); + + // Destination objects were move-constructed with correct values + for (size_t i = 0; i < N; ++i) + { + CHECK_EQUAL(static_cast(i + 1), dst[i].value); + CHECK(dst[i].was_moved_into); + } + + // Destructors were called for the N source objects + CHECK_EQUAL(static_cast(N), relocatable_t::destructor_count); + + // Clean up destination objects + relocatable_t::reset_counts(); + for (size_t i = 0; i < N; ++i) + { + dst[i].~relocatable_t(); + } + } + + //************************************************************************* + TEST(test_relocate_non_trivial_same_location) + { + const size_t N = 5; + + alignas(relocatable_t) unsigned char buffer[sizeof(relocatable_t) * N]; + relocatable_t* p = reinterpret_cast(buffer); + + // Placement-new objects + for (size_t i = 0; i < N; ++i) + { + ::new (static_cast(p + i)) relocatable_t(static_cast(i + 1)); + } + + relocatable_t::reset_counts(); + + // Relocating to the same location should be a no-op (early return) + relocatable_t* result = etl::relocate(p, p + N, p); + + CHECK(result == p + N); + + // No destructors should have been called (no move-and-destroy performed) + CHECK_EQUAL(0, relocatable_t::destructor_count); + + // Values should be unchanged + for (size_t i = 0; i < N; ++i) + { + CHECK_EQUAL(static_cast(i + 1), p[i].value); + CHECK(!p[i].was_moved_into); + } + + // Clean up + relocatable_t::reset_counts(); + for (size_t i = 0; i < N; ++i) + { + p[i].~relocatable_t(); + } + } + + //************************************************************************* + TEST(test_relocate_non_trivial_empty_range) + { + alignas(relocatable_t) unsigned char src_buffer[sizeof(relocatable_t)]; + alignas(relocatable_t) unsigned char dst_buffer[sizeof(relocatable_t)]; + + relocatable_t* src = reinterpret_cast(src_buffer); + relocatable_t* dst = reinterpret_cast(dst_buffer); + + relocatable_t::reset_counts(); + + // Empty range: first == last + relocatable_t* result = etl::relocate(src, src, dst); + + CHECK(result == dst); + + // No destructors should have been called + CHECK_EQUAL(0, relocatable_t::destructor_count); + } +#endif } } // namespace diff --git a/test/test_multiset.cpp b/test/test_multiset.cpp index c040e8ac..6cf29f87 100644 --- a/test/test_multiset.cpp +++ b/test/test_multiset.cpp @@ -98,10 +98,10 @@ namespace return (lhs < rhs.k); } +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_multiset) { //************************************************************************* -#include "etl/private/diagnostic_null_dereference_push.h" template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) { @@ -118,7 +118,6 @@ namespace return true; } -#include "etl/private/diagnostic_pop.h" //************************************************************************* struct SetupFixture @@ -1515,7 +1514,6 @@ namespace for (pos = data.crbegin(); pos != data.crend(); ++pos) { -#include "etl/private/diagnostic_null_dereference_push.h" if (*pos > prv) { pass = false; @@ -1523,7 +1521,6 @@ namespace } prv = *pos; -#include "etl/private/diagnostic_pop.h" } CHECK(pass); @@ -1630,4 +1627,5 @@ namespace } while (std::next_permutation(permutation.begin(), permutation.end())); } } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_numeric.cpp b/test/test_numeric.cpp index 1f6980bc..f7407fef 100644 --- a/test/test_numeric.cpp +++ b/test/test_numeric.cpp @@ -206,5 +206,411 @@ namespace CHECK_CLOSE(10.0, etl::lerp(10.0, 10.0, 1), 0.001); CHECK_CLOSE(10.0, etl::lerp(10, 10, 1), 0.001); } + + //************************************************************************* + TEST(test_add_sat_unsigned) + { + // Normal addition (no overflow) + CHECK_EQUAL(uint8_t(0), etl::add_sat(uint8_t(0), uint8_t(0))); + CHECK_EQUAL(uint8_t(3), etl::add_sat(uint8_t(1), uint8_t(2))); + CHECK_EQUAL(uint8_t(254), etl::add_sat(uint8_t(127), uint8_t(127))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(200), uint8_t(55))); + + // Overflow saturates to max + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(255), uint8_t(1))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(1), uint8_t(255))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(255), uint8_t(255))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(200), uint8_t(200))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(128), uint8_t(128))); + + // Identity: adding zero + CHECK_EQUAL(uint8_t(42), etl::add_sat(uint8_t(42), uint8_t(0))); + CHECK_EQUAL(uint8_t(0), etl::add_sat(uint8_t(0), uint8_t(0))); + CHECK_EQUAL(uint8_t(255), etl::add_sat(uint8_t(255), uint8_t(0))); + + // uint16_t + CHECK_EQUAL(uint16_t(65535), etl::add_sat(uint16_t(65535), uint16_t(1))); + CHECK_EQUAL(uint16_t(65535), etl::add_sat(uint16_t(65535), uint16_t(65535))); + CHECK_EQUAL(uint16_t(1000), etl::add_sat(uint16_t(500), uint16_t(500))); + + // uint32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::add_sat(std::numeric_limits::max(), uint32_t(1))); + CHECK_EQUAL(std::numeric_limits::max(), etl::add_sat(std::numeric_limits::max(), std::numeric_limits::max())); + CHECK_EQUAL(uint32_t(100), etl::add_sat(uint32_t(60), uint32_t(40))); + } + + //************************************************************************* + TEST(test_add_sat_signed) + { + // Normal addition (no overflow) + CHECK_EQUAL(int8_t(0), etl::add_sat(int8_t(0), int8_t(0))); + CHECK_EQUAL(int8_t(3), etl::add_sat(int8_t(1), int8_t(2))); + CHECK_EQUAL(int8_t(-3), etl::add_sat(int8_t(-1), int8_t(-2))); + CHECK_EQUAL(int8_t(0), etl::add_sat(int8_t(1), int8_t(-1))); + CHECK_EQUAL(int8_t(0), etl::add_sat(int8_t(-1), int8_t(1))); + CHECK_EQUAL(int8_t(126), etl::add_sat(int8_t(63), int8_t(63))); + + // Positive overflow saturates to max + CHECK_EQUAL(int8_t(127), etl::add_sat(int8_t(127), int8_t(1))); + CHECK_EQUAL(int8_t(127), etl::add_sat(int8_t(1), int8_t(127))); + CHECK_EQUAL(int8_t(127), etl::add_sat(int8_t(127), int8_t(127))); + CHECK_EQUAL(int8_t(127), etl::add_sat(int8_t(100), int8_t(100))); + + // Negative overflow saturates to min + CHECK_EQUAL(int8_t(-128), etl::add_sat(int8_t(-128), int8_t(-1))); + CHECK_EQUAL(int8_t(-128), etl::add_sat(int8_t(-1), int8_t(-128))); + CHECK_EQUAL(int8_t(-128), etl::add_sat(int8_t(-128), int8_t(-128))); + CHECK_EQUAL(int8_t(-128), etl::add_sat(int8_t(-100), int8_t(-100))); + + // Mixed signs: no overflow possible + CHECK_EQUAL(int8_t(-1), etl::add_sat(int8_t(127), int8_t(-128))); + CHECK_EQUAL(int8_t(-1), etl::add_sat(int8_t(-128), int8_t(127))); + CHECK_EQUAL(int8_t(27), etl::add_sat(int8_t(127), int8_t(-100))); + CHECK_EQUAL(int8_t(-28), etl::add_sat(int8_t(-128), int8_t(100))); + + // Identity: adding zero + CHECK_EQUAL(int8_t(42), etl::add_sat(int8_t(42), int8_t(0))); + CHECK_EQUAL(int8_t(-42), etl::add_sat(int8_t(-42), int8_t(0))); + CHECK_EQUAL(int8_t(127), etl::add_sat(int8_t(127), int8_t(0))); + CHECK_EQUAL(int8_t(-128), etl::add_sat(int8_t(-128), int8_t(0))); + + // int16_t + CHECK_EQUAL(int16_t(32767), etl::add_sat(int16_t(32767), int16_t(1))); + CHECK_EQUAL(int16_t(-32768), etl::add_sat(int16_t(-32768), int16_t(-1))); + CHECK_EQUAL(int16_t(32767), etl::add_sat(int16_t(32767), int16_t(32767))); + CHECK_EQUAL(int16_t(-32768), etl::add_sat(int16_t(-32768), int16_t(-32768))); + CHECK_EQUAL(int16_t(1000), etl::add_sat(int16_t(500), int16_t(500))); + + // int32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::add_sat(std::numeric_limits::max(), int32_t(1))); + CHECK_EQUAL(std::numeric_limits::min(), etl::add_sat(std::numeric_limits::min(), int32_t(-1))); + CHECK_EQUAL(std::numeric_limits::max(), etl::add_sat(std::numeric_limits::max(), std::numeric_limits::max())); + CHECK_EQUAL(std::numeric_limits::min(), etl::add_sat(std::numeric_limits::min(), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(100), etl::add_sat(int32_t(60), int32_t(40))); + } + + //************************************************************************* + TEST(test_sub_sat_unsigned) + { + // Normal subtraction (no underflow) + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(0), uint8_t(0))); + CHECK_EQUAL(uint8_t(1), etl::sub_sat(uint8_t(3), uint8_t(2))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(2), uint8_t(2))); + CHECK_EQUAL(uint8_t(255), etl::sub_sat(uint8_t(255), uint8_t(0))); + CHECK_EQUAL(uint8_t(128), etl::sub_sat(uint8_t(255), uint8_t(127))); + + // Underflow saturates to 0 + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(0), uint8_t(1))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(0), uint8_t(255))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(1), uint8_t(2))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(100), uint8_t(200))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(127), uint8_t(255))); + + // Identity: subtracting zero + CHECK_EQUAL(uint8_t(42), etl::sub_sat(uint8_t(42), uint8_t(0))); + CHECK_EQUAL(uint8_t(0), etl::sub_sat(uint8_t(0), uint8_t(0))); + CHECK_EQUAL(uint8_t(255), etl::sub_sat(uint8_t(255), uint8_t(0))); + + // uint16_t + CHECK_EQUAL(uint16_t(0), etl::sub_sat(uint16_t(0), uint16_t(1))); + CHECK_EQUAL(uint16_t(0), etl::sub_sat(uint16_t(0), uint16_t(65535))); + CHECK_EQUAL(uint16_t(100), etl::sub_sat(uint16_t(500), uint16_t(400))); + + // uint32_t + CHECK_EQUAL(uint32_t(0), etl::sub_sat(uint32_t(0), uint32_t(1))); + CHECK_EQUAL(uint32_t(0), etl::sub_sat(uint32_t(0), std::numeric_limits::max())); + CHECK_EQUAL(uint32_t(1), etl::sub_sat(std::numeric_limits::max(), std::numeric_limits::max() - 1)); + CHECK_EQUAL(uint32_t(20), etl::sub_sat(uint32_t(60), uint32_t(40))); + } + + //************************************************************************* + TEST(test_sub_sat_signed) + { + // Normal subtraction (no overflow) + CHECK_EQUAL(int8_t(0), etl::sub_sat(int8_t(0), int8_t(0))); + CHECK_EQUAL(int8_t(1), etl::sub_sat(int8_t(3), int8_t(2))); + CHECK_EQUAL(int8_t(-1), etl::sub_sat(int8_t(2), int8_t(3))); + CHECK_EQUAL(int8_t(0), etl::sub_sat(int8_t(1), int8_t(1))); + CHECK_EQUAL(int8_t(-2), etl::sub_sat(int8_t(-1), int8_t(1))); + CHECK_EQUAL(int8_t(2), etl::sub_sat(int8_t(1), int8_t(-1))); + + // Positive overflow: subtracting large negative from positive saturates to max + CHECK_EQUAL(int8_t(127), etl::sub_sat(int8_t(127), int8_t(-1))); + CHECK_EQUAL(int8_t(127), etl::sub_sat(int8_t(1), int8_t(-127))); + CHECK_EQUAL(int8_t(127), etl::sub_sat(int8_t(127), int8_t(-128))); + CHECK_EQUAL(int8_t(127), etl::sub_sat(int8_t(100), int8_t(-100))); + + // Negative overflow: subtracting large positive from negative saturates to min + CHECK_EQUAL(int8_t(-128), etl::sub_sat(int8_t(-128), int8_t(1))); + CHECK_EQUAL(int8_t(-128), etl::sub_sat(int8_t(-1), int8_t(127))); + CHECK_EQUAL(int8_t(-128), etl::sub_sat(int8_t(-128), int8_t(127))); + CHECK_EQUAL(int8_t(-128), etl::sub_sat(int8_t(-100), int8_t(100))); + + // No overflow when same sign + CHECK_EQUAL(int8_t(0), etl::sub_sat(int8_t(-128), int8_t(-128))); + CHECK_EQUAL(int8_t(-1), etl::sub_sat(int8_t(-128), int8_t(-127))); + + // Identity: subtracting zero + CHECK_EQUAL(int8_t(42), etl::sub_sat(int8_t(42), int8_t(0))); + CHECK_EQUAL(int8_t(-42), etl::sub_sat(int8_t(-42), int8_t(0))); + CHECK_EQUAL(int8_t(127), etl::sub_sat(int8_t(127), int8_t(0))); + CHECK_EQUAL(int8_t(-128), etl::sub_sat(int8_t(-128), int8_t(0))); + + // int16_t + CHECK_EQUAL(int16_t(32767), etl::sub_sat(int16_t(32767), int16_t(-1))); + CHECK_EQUAL(int16_t(-32768), etl::sub_sat(int16_t(-32768), int16_t(1))); + CHECK_EQUAL(int16_t(32767), etl::sub_sat(int16_t(32767), int16_t(-32768))); + CHECK_EQUAL(int16_t(-32768), etl::sub_sat(int16_t(-32768), int16_t(32767))); + CHECK_EQUAL(int16_t(100), etl::sub_sat(int16_t(500), int16_t(400))); + + // int32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::sub_sat(std::numeric_limits::max(), int32_t(-1))); + CHECK_EQUAL(std::numeric_limits::min(), etl::sub_sat(std::numeric_limits::min(), int32_t(1))); + CHECK_EQUAL(std::numeric_limits::max(), etl::sub_sat(std::numeric_limits::max(), std::numeric_limits::min())); + CHECK_EQUAL(std::numeric_limits::min(), etl::sub_sat(std::numeric_limits::min(), std::numeric_limits::max())); + CHECK_EQUAL(int32_t(20), etl::sub_sat(int32_t(60), int32_t(40))); + } + + //************************************************************************* + TEST(test_mul_sat_unsigned) + { + // Normal multiplication (no overflow) + CHECK_EQUAL(uint8_t(0), etl::mul_sat(uint8_t(0), uint8_t(0))); + CHECK_EQUAL(uint8_t(0), etl::mul_sat(uint8_t(0), uint8_t(255))); + CHECK_EQUAL(uint8_t(0), etl::mul_sat(uint8_t(255), uint8_t(0))); + CHECK_EQUAL(uint8_t(6), etl::mul_sat(uint8_t(2), uint8_t(3))); + CHECK_EQUAL(uint8_t(1), etl::mul_sat(uint8_t(1), uint8_t(1))); + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(255), uint8_t(1))); + CHECK_EQUAL(uint8_t(250), etl::mul_sat(uint8_t(25), uint8_t(10))); + + // Overflow saturates to max + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(255), uint8_t(2))); + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(2), uint8_t(255))); + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(255), uint8_t(255))); + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(128), uint8_t(3))); + CHECK_EQUAL(uint8_t(255), etl::mul_sat(uint8_t(16), uint8_t(16))); + + // uint16_t + CHECK_EQUAL(uint16_t(65535), etl::mul_sat(uint16_t(65535), uint16_t(2))); + CHECK_EQUAL(uint16_t(65535), etl::mul_sat(uint16_t(65535), uint16_t(65535))); + CHECK_EQUAL(uint16_t(10000), etl::mul_sat(uint16_t(100), uint16_t(100))); + + // uint32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::mul_sat(std::numeric_limits::max(), uint32_t(2))); + CHECK_EQUAL(std::numeric_limits::max(), etl::mul_sat(std::numeric_limits::max(), std::numeric_limits::max())); + CHECK_EQUAL(uint32_t(600), etl::mul_sat(uint32_t(20), uint32_t(30))); + } + + //************************************************************************* + TEST(test_mul_sat_signed) + { + // Normal multiplication (no overflow) + CHECK_EQUAL(int8_t(0), etl::mul_sat(int8_t(0), int8_t(0))); + CHECK_EQUAL(int8_t(0), etl::mul_sat(int8_t(0), int8_t(127))); + CHECK_EQUAL(int8_t(0), etl::mul_sat(int8_t(0), int8_t(-128))); + CHECK_EQUAL(int8_t(6), etl::mul_sat(int8_t(2), int8_t(3))); + CHECK_EQUAL(int8_t(-6), etl::mul_sat(int8_t(2), int8_t(-3))); + CHECK_EQUAL(int8_t(-6), etl::mul_sat(int8_t(-2), int8_t(3))); + CHECK_EQUAL(int8_t(6), etl::mul_sat(int8_t(-2), int8_t(-3))); + CHECK_EQUAL(int8_t(1), etl::mul_sat(int8_t(1), int8_t(1))); + CHECK_EQUAL(int8_t(-1), etl::mul_sat(int8_t(1), int8_t(-1))); + CHECK_EQUAL(int8_t(1), etl::mul_sat(int8_t(-1), int8_t(-1))); + CHECK_EQUAL(int8_t(100), etl::mul_sat(int8_t(10), int8_t(10))); + + // Positive overflow: both positive + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(127), int8_t(2))); + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(2), int8_t(127))); + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(127), int8_t(127))); + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(64), int8_t(3))); + + // Positive overflow: both negative + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(-128), int8_t(-2))); + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(-2), int8_t(-128))); + CHECK_EQUAL(int8_t(127), etl::mul_sat(int8_t(-128), int8_t(-128))); + + // Negative overflow: positive * negative + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(127), int8_t(-2))); + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(2), int8_t(-127))); + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(127), int8_t(-128))); + + // Negative overflow: negative * positive + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(-128), int8_t(2))); + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(-2), int8_t(127))); + CHECK_EQUAL(int8_t(-128), etl::mul_sat(int8_t(-128), int8_t(127))); + + // int16_t + CHECK_EQUAL(int16_t(32767), etl::mul_sat(int16_t(32767), int16_t(2))); + CHECK_EQUAL(int16_t(-32768), etl::mul_sat(int16_t(32767), int16_t(-2))); + CHECK_EQUAL(int16_t(32767), etl::mul_sat(int16_t(-32768), int16_t(-2))); + CHECK_EQUAL(int16_t(-32768), etl::mul_sat(int16_t(-32768), int16_t(2))); + CHECK_EQUAL(int16_t(10000), etl::mul_sat(int16_t(100), int16_t(100))); + + // int32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::mul_sat(std::numeric_limits::max(), int32_t(2))); + CHECK_EQUAL(std::numeric_limits::min(), etl::mul_sat(std::numeric_limits::max(), int32_t(-2))); + CHECK_EQUAL(std::numeric_limits::max(), etl::mul_sat(std::numeric_limits::min(), int32_t(-2))); + CHECK_EQUAL(std::numeric_limits::min(), etl::mul_sat(std::numeric_limits::min(), int32_t(2))); + CHECK_EQUAL(int32_t(600), etl::mul_sat(int32_t(20), int32_t(30))); + } + + //************************************************************************* + TEST(test_div_sat_unsigned) + { + // Normal division + CHECK_EQUAL(uint8_t(0), etl::div_sat(uint8_t(0), uint8_t(1))); + CHECK_EQUAL(uint8_t(0), etl::div_sat(uint8_t(0), uint8_t(255))); + CHECK_EQUAL(uint8_t(1), etl::div_sat(uint8_t(1), uint8_t(1))); + CHECK_EQUAL(uint8_t(3), etl::div_sat(uint8_t(6), uint8_t(2))); + CHECK_EQUAL(uint8_t(127), etl::div_sat(uint8_t(255), uint8_t(2))); + CHECK_EQUAL(uint8_t(255), etl::div_sat(uint8_t(255), uint8_t(1))); + CHECK_EQUAL(uint8_t(0), etl::div_sat(uint8_t(1), uint8_t(2))); + + // uint16_t + CHECK_EQUAL(uint16_t(32767), etl::div_sat(uint16_t(65535), uint16_t(2))); + CHECK_EQUAL(uint16_t(65535), etl::div_sat(uint16_t(65535), uint16_t(1))); + CHECK_EQUAL(uint16_t(100), etl::div_sat(uint16_t(1000), uint16_t(10))); + + // uint32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::div_sat(std::numeric_limits::max(), uint32_t(1))); + CHECK_EQUAL(uint32_t(1), etl::div_sat(std::numeric_limits::max(), std::numeric_limits::max())); + CHECK_EQUAL(uint32_t(30), etl::div_sat(uint32_t(600), uint32_t(20))); + } + + //************************************************************************* + TEST(test_div_sat_signed) + { + // Normal division + CHECK_EQUAL(int8_t(0), etl::div_sat(int8_t(0), int8_t(1))); + CHECK_EQUAL(int8_t(0), etl::div_sat(int8_t(0), int8_t(-1))); + CHECK_EQUAL(int8_t(1), etl::div_sat(int8_t(1), int8_t(1))); + CHECK_EQUAL(int8_t(-1), etl::div_sat(int8_t(1), int8_t(-1))); + CHECK_EQUAL(int8_t(-1), etl::div_sat(int8_t(-1), int8_t(1))); + CHECK_EQUAL(int8_t(1), etl::div_sat(int8_t(-1), int8_t(-1))); + CHECK_EQUAL(int8_t(3), etl::div_sat(int8_t(6), int8_t(2))); + CHECK_EQUAL(int8_t(-3), etl::div_sat(int8_t(6), int8_t(-2))); + CHECK_EQUAL(int8_t(-3), etl::div_sat(int8_t(-6), int8_t(2))); + CHECK_EQUAL(int8_t(3), etl::div_sat(int8_t(-6), int8_t(-2))); + CHECK_EQUAL(int8_t(127), etl::div_sat(int8_t(127), int8_t(1))); + CHECK_EQUAL(int8_t(-127), etl::div_sat(int8_t(127), int8_t(-1))); + CHECK_EQUAL(int8_t(-128), etl::div_sat(int8_t(-128), int8_t(1))); + CHECK_EQUAL(int8_t(0), etl::div_sat(int8_t(1), int8_t(2))); + + // The only overflow case: min / -1 saturates to max + CHECK_EQUAL(int8_t(127), etl::div_sat(int8_t(-128), int8_t(-1))); + + // int16_t + CHECK_EQUAL(int16_t(32767), etl::div_sat(int16_t(-32768), int16_t(-1))); + CHECK_EQUAL(int16_t(-32768), etl::div_sat(int16_t(-32768), int16_t(1))); + CHECK_EQUAL(int16_t(100), etl::div_sat(int16_t(1000), int16_t(10))); + + // int32_t + CHECK_EQUAL(std::numeric_limits::max(), etl::div_sat(std::numeric_limits::min(), int32_t(-1))); + CHECK_EQUAL(std::numeric_limits::min(), etl::div_sat(std::numeric_limits::min(), int32_t(1))); + CHECK_EQUAL(std::numeric_limits::max(), etl::div_sat(std::numeric_limits::max(), int32_t(1))); + CHECK_EQUAL(int32_t(0), etl::div_sat(std::numeric_limits::max(), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(30), etl::div_sat(int32_t(600), int32_t(20))); + } + + //************************************************************************* + TEST(test_saturate_cast_unsigned_to_unsigned) + { + // Fits + CHECK_EQUAL(uint8_t(42), (etl::saturate_cast(uint16_t(42)))); + CHECK_EQUAL(uint8_t(0), (etl::saturate_cast(uint16_t(0)))); + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(uint16_t(255)))); + + // Overflow: clamp to max + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(uint16_t(256)))); + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(uint16_t(1000)))); + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(uint16_t(65535)))); + + // Widening (always fits) + CHECK_EQUAL(uint16_t(42), (etl::saturate_cast(uint8_t(42)))); + CHECK_EQUAL(uint16_t(255), (etl::saturate_cast(uint8_t(255)))); + } + + //************************************************************************* + TEST(test_saturate_cast_signed_to_signed) + { + // Fits + CHECK_EQUAL(int8_t(42), (etl::saturate_cast(int16_t(42)))); + CHECK_EQUAL(int8_t(-42), (etl::saturate_cast(int16_t(-42)))); + CHECK_EQUAL(int8_t(0), (etl::saturate_cast(int16_t(0)))); + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(int16_t(127)))); + CHECK_EQUAL(int8_t(-128), (etl::saturate_cast(int16_t(-128)))); + + // Overflow: clamp to max + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(int16_t(128)))); + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(int16_t(1000)))); + + // Underflow: clamp to min + CHECK_EQUAL(int8_t(-128), (etl::saturate_cast(int16_t(-129)))); + CHECK_EQUAL(int8_t(-128), (etl::saturate_cast(int16_t(-1000)))); + + // Widening (always fits) + CHECK_EQUAL(int16_t(42), (etl::saturate_cast(int8_t(42)))); + CHECK_EQUAL(int16_t(-128), (etl::saturate_cast(int8_t(-128)))); + } + + //************************************************************************* + TEST(test_saturate_cast_signed_to_unsigned) + { + // Fits + CHECK_EQUAL(uint8_t(42), (etl::saturate_cast(int16_t(42)))); + CHECK_EQUAL(uint8_t(0), (etl::saturate_cast(int16_t(0)))); + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(int16_t(255)))); + + // Negative source: clamp to 0 + CHECK_EQUAL(uint8_t(0), (etl::saturate_cast(int16_t(-1)))); + CHECK_EQUAL(uint8_t(0), (etl::saturate_cast(int16_t(-1000)))); + CHECK_EQUAL(uint16_t(0), (etl::saturate_cast(int16_t(-1)))); + + // Overflow: clamp to max + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(int16_t(256)))); + CHECK_EQUAL(uint8_t(255), (etl::saturate_cast(int16_t(1000)))); + } + + //************************************************************************* + TEST(test_saturate_cast_unsigned_to_signed) + { + // Fits + CHECK_EQUAL(int8_t(42), (etl::saturate_cast(uint16_t(42)))); + CHECK_EQUAL(int8_t(0), (etl::saturate_cast(uint16_t(0)))); + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(uint16_t(127)))); + + // Overflow: clamp to max + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(uint16_t(128)))); + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(uint16_t(1000)))); + CHECK_EQUAL(int8_t(127), (etl::saturate_cast(uint16_t(65535)))); + + // Widening (always fits) + CHECK_EQUAL(int16_t(255), (etl::saturate_cast(uint8_t(255)))); + CHECK_EQUAL(int16_t(0), (etl::saturate_cast(uint8_t(0)))); + } + + //************************************************************************* + TEST(test_saturate_cast_same_type) + { + // Same type, no conversion needed + CHECK_EQUAL(int32_t(42), (etl::saturate_cast(int32_t(42)))); + CHECK_EQUAL(uint32_t(42), (etl::saturate_cast(uint32_t(42)))); + CHECK_EQUAL(int32_t(-42), (etl::saturate_cast(int32_t(-42)))); + } + + //************************************************************************* + TEST(test_saturate_cast_boundary_values) + { + // int32_t max -> uint16_t + CHECK_EQUAL(uint16_t(65535), (etl::saturate_cast(int32_t(2147483647)))); + + // int32_t min -> uint16_t + CHECK_EQUAL(uint16_t(0), (etl::saturate_cast(std::numeric_limits::min()))); + + // uint32_t max -> int32_t + CHECK_EQUAL(std::numeric_limits::max(), (etl::saturate_cast(std::numeric_limits::max()))); + + // uint32_t max -> int16_t + CHECK_EQUAL(int16_t(32767), (etl::saturate_cast(std::numeric_limits::max()))); + } } } // namespace diff --git a/test/test_optional.cpp b/test/test_optional.cpp index a848b0cb..88242053 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include #include #include +#include #include #include "data.h" @@ -1176,5 +1177,164 @@ namespace CHECK_EQUAL(99, opt->_some); } #endif + + //************************************************************************* + // Tests for noexcept properties of etl::optional + // The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled, + // because ETL_NOEXCEPT_IF expands to nothing otherwise. + // The etl::is_nothrow_* traits only work with STL or builtins. + //************************************************************************* +#if ETL_USING_CPP11 && ETL_USING_EXCEPTIONS && (defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS))) + struct NothrowCopyMove + { + NothrowCopyMove() noexcept {} + NothrowCopyMove(const NothrowCopyMove&) noexcept {} + NothrowCopyMove(NothrowCopyMove&&) noexcept {} + NothrowCopyMove& operator=(const NothrowCopyMove&) noexcept + { + return *this; + } + NothrowCopyMove& operator=(NothrowCopyMove&&) noexcept + { + return *this; + } + }; + + struct ThrowingCopy + { + ThrowingCopy() noexcept {} + ThrowingCopy(const ThrowingCopy&) {} // may throw + ThrowingCopy(ThrowingCopy&&) noexcept {} + ThrowingCopy& operator=(const ThrowingCopy&) + { + return *this; + } // may throw + ThrowingCopy& operator=(ThrowingCopy&&) noexcept + { + return *this; + } + }; + + struct ThrowingMove + { + ThrowingMove() noexcept {} + ThrowingMove(const ThrowingMove&) noexcept {} + ThrowingMove(ThrowingMove&&) {} // may throw + ThrowingMove& operator=(const ThrowingMove&) noexcept + { + return *this; + } + ThrowingMove& operator=(ThrowingMove&&) + { + return *this; + } // may throw + }; + + struct ThrowingBoth + { + ThrowingBoth() noexcept {} + ThrowingBoth(const ThrowingBoth&) {} // may throw + ThrowingBoth(ThrowingBoth&&) {} // may throw + ThrowingBoth& operator=(const ThrowingBoth&) + { + return *this; + } + ThrowingBoth& operator=(ThrowingBoth&&) + { + return *this; + } + }; + + TEST(test_optional_nothrow_copy_constructible) + { + // When T is nothrow copy constructible, optional should be too + static_assert(etl::is_nothrow_copy_constructible>::value, "optional should be nothrow copy constructible"); + static_assert(etl::is_nothrow_copy_constructible>::value, + "optional should be nothrow copy constructible"); + + // When T is NOT nothrow copy constructible, optional should not be either + static_assert(!etl::is_nothrow_copy_constructible>::value, + "optional should NOT be nothrow copy constructible"); + static_assert(!etl::is_nothrow_copy_constructible>::value, + "optional should NOT be nothrow copy constructible"); + + // ThrowingMove has nothrow copy but throwing move + static_assert(etl::is_nothrow_copy_constructible>::value, + "optional should be nothrow copy constructible"); + + CHECK(true); // Placeholder for the static_asserts above + } + + TEST(test_optional_nothrow_move_constructible) + { + // When T is nothrow move constructible, optional should be too + static_assert(etl::is_nothrow_move_constructible>::value, "optional should be nothrow move constructible"); + static_assert(etl::is_nothrow_move_constructible>::value, + "optional should be nothrow move constructible"); + + // When T is NOT nothrow move constructible, optional should not be either + static_assert(!etl::is_nothrow_move_constructible>::value, + "optional should NOT be nothrow move constructible"); + static_assert(!etl::is_nothrow_move_constructible>::value, + "optional should NOT be nothrow move constructible"); + + // ThrowingCopy has nothrow move but throwing copy + static_assert(etl::is_nothrow_move_constructible>::value, + "optional should be nothrow move constructible"); + + CHECK(true); // Placeholder for the static_asserts above + } + + TEST(test_optional_nothrow_default_constructible) + { + // Default construction of optional should always be noexcept + static_assert(etl::is_nothrow_default_constructible>::value, "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + + CHECK(true); + } + + TEST(test_optional_nothrow_constructible_from_value) + { + // optional(U&&) should be noexcept iff T is nothrow constructible from U&& + static_assert(etl::is_nothrow_constructible, int>::value, "optional should be nothrow constructible from int"); + static_assert(etl::is_nothrow_constructible, int&&>::value, "optional should be nothrow constructible from int&&"); + + CHECK(true); + } + + TEST(test_optional_nothrow_copy_assignable) + { + // Copy assignment should propagate noexcept from T + static_assert(etl::is_nothrow_copy_assignable>::value, "optional should be nothrow copy assignable"); + static_assert(etl::is_nothrow_copy_assignable>::value, + "optional should be nothrow copy assignable"); + + // ThrowingCopy has a throwing copy constructor, so copy assignment should not be noexcept + static_assert(!etl::is_nothrow_copy_assignable>::value, + "optional should NOT be nothrow copy assignable"); + + CHECK(true); + } + + TEST(test_optional_nothrow_move_assignable) + { + // Move assignment should propagate noexcept from T + static_assert(etl::is_nothrow_move_assignable>::value, "optional should be nothrow move assignable"); + static_assert(etl::is_nothrow_move_assignable>::value, + "optional should be nothrow move assignable"); + + // ThrowingMove has a throwing move constructor, so move assignment should not be noexcept + static_assert(!etl::is_nothrow_move_assignable>::value, + "optional should NOT be nothrow move assignable"); + + CHECK(true); + } +#endif } } // namespace diff --git a/test/test_ranges.cpp b/test/test_ranges.cpp index 0fe4c41b..01b20c95 100644 --- a/test/test_ranges.cpp +++ b/test/test_ranges.cpp @@ -157,6 +157,7 @@ namespace std namespace { + #include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_ranges) { //************************************************************************* @@ -5740,6 +5741,7 @@ namespace CHECK_EQUAL(30, v_out[2]); } } + #include "etl/private/diagnostic_pop.h" } // namespace #endif diff --git a/test/test_set.cpp b/test/test_set.cpp index f8f56d50..2fb624d4 100644 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -103,10 +103,10 @@ namespace // return (lhs.k < rhs.k); // } +#include "etl/private/diagnostic_null_dereference_push.h" SUITE(test_set) { //************************************************************************* -#include "etl/private/diagnostic_null_dereference_push.h" template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) { @@ -123,7 +123,6 @@ namespace return true; } -#include "etl/private/diagnostic_pop.h" //************************************************************************* struct SetupFixture @@ -595,8 +594,8 @@ namespace for (size_t i = 0; i < MAX_SIZE; ++i) { - data_result = data.insert(i); - compare_result = compare_data.insert(i); + data_result = data.insert(static_cast(i)); + compare_result = compare_data.insert(static_cast(i)); // Check that both return successful return results CHECK_EQUAL(*data_result.first, *compare_result.first); @@ -609,8 +608,8 @@ namespace // not throw error for (size_t i = 0; i < MAX_SIZE; ++i) { - data_result = data.insert(i); - compare_result = compare_data.insert(i); + data_result = data.insert(static_cast(i)); + compare_result = compare_data.insert(static_cast(i)); // Check that both return successful return results CHECK_EQUAL(*data_result.first, *compare_result.first); @@ -1443,4 +1442,5 @@ namespace } while (std::next_permutation(permutation.begin(), permutation.end())); } } +#include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index c49b2eda..f6ef4cda 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -102,8 +102,8 @@ namespace return *this; } - Copyable(Copyable&&) = delete; - Copyable& operator=(Copyable&) = delete; + Copyable(Copyable&&) = delete; + Copyable& operator=(Copyable&&) = delete; }; //********************************************* @@ -146,8 +146,8 @@ namespace return *this; } - NotDefaultConstructible(NotDefaultConstructible&&) = delete; - NotDefaultConstructible& operator=(NotDefaultConstructible&) = delete; + NotDefaultConstructible(NotDefaultConstructible&&) = delete; + NotDefaultConstructible& operator=(NotDefaultConstructible&&) = delete; }; // A function to test etl::type_identity. @@ -344,7 +344,7 @@ using etl::is_move_constructible; //************************* template <> -struct etl::is_assignable : public etl::true_type +struct etl::is_assignable : public etl::false_type { }; @@ -364,7 +364,7 @@ struct etl::is_copy_assignable : public etl::true_type }; template <> -struct etl::is_move_assignable : public etl::true_type +struct etl::is_move_assignable : public etl::false_type { }; @@ -1007,6 +1007,64 @@ namespace CHECK((std::is_base_of::value) == (etl::is_base_of::value)); } +#if ETL_USING_BUILTIN_IS_VIRTUAL_BASE_OF + //************************************************************************* + TEST(test_is_virtual_base_of) + { + struct A + { + }; + struct B : public A // Non-virtual base + { + }; + struct C : virtual public A // Virtual base + { + }; + struct D + : public B + , virtual public A // A is both virtual and non-virtual base + { + }; + struct E : public C // A is indirect virtual base + { + }; + struct F // Unrelated class + { + }; + + // A is not a virtual base of A (same class) + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + + // A is NOT a virtual base of B (it's a non-virtual base) + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + + // A IS a virtual base of C + CHECK_EQUAL(true, (etl::is_virtual_base_of::value)); + + // A IS a virtual base of D (even though it's also a non-virtual base via B) + CHECK_EQUAL(true, (etl::is_virtual_base_of::value)); + + // A IS a virtual base of E (indirect virtual base) + CHECK_EQUAL(true, (etl::is_virtual_base_of::value)); + + // Unrelated classes + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + + // Fundamental types + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + CHECK_EQUAL(false, (etl::is_virtual_base_of::value)); + + #if ETL_USING_CPP17 + // Test the _v helper + CHECK_EQUAL(false, etl::is_virtual_base_of_v); + CHECK_EQUAL(true, etl::is_virtual_base_of_v); + CHECK_EQUAL(true, etl::is_virtual_base_of_v); + CHECK_EQUAL(true, etl::is_virtual_base_of_v); + #endif + } +#endif + //************************************************************************* TEST(test_types) { @@ -1490,6 +1548,155 @@ namespace #endif } + //************************************************************************* + TEST(test_is_nothrow_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_constructible::value) == true); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_default_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_default_constructible::value) == true); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_copy_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_copy_constructible::value) == true); + CHECK((etl::is_nothrow_copy_constructible::value) == true); + CHECK((etl::is_nothrow_copy_constructible::value) == false); + CHECK((etl::is_nothrow_copy_constructible::value) == false); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_move_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == false); + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == false); + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) + == (std::is_nothrow_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK( + (etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_copy_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_copy_assignable::value) == true); + CHECK((etl::is_nothrow_copy_assignable::value) == true); + CHECK((etl::is_nothrow_copy_assignable::value) == false); + CHECK((etl::is_nothrow_copy_assignable::value) == false); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_move_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == false); + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + #endif +#endif + } + //************************************************************************* TEST(test_is_trivially_constructible) { @@ -1574,6 +1781,110 @@ namespace #endif } + //************************************************************************* + TEST(test_is_trivially_relocatable) + { + // Trivially relocatable types (trivially copyable and trivially destructible) + // Primitive types should always be detected as trivially relocatable + CHECK_TRUE(etl::is_trivially_relocatable::value); + CHECK_TRUE(etl::is_trivially_relocatable::value); + CHECK_TRUE(etl::is_trivially_relocatable::value); + CHECK_TRUE(etl::is_trivially_relocatable::value); + + // POD struct should be trivially relocatable when proper detection is available + struct TrivialStruct + { + int x; + double y; + }; + + // Struct with non-trivial destructor should NOT be trivially relocatable + struct NonTrivialDestructor + { + ~NonTrivialDestructor() {} + }; + CHECK_FALSE(etl::is_trivially_relocatable::value); + + // Struct with non-trivial copy constructor should NOT be trivially relocatable + struct NonTrivialCopy + { + NonTrivialCopy() = default; + NonTrivialCopy(const NonTrivialCopy&) {} + NonTrivialCopy& operator=(const NonTrivialCopy&) = default; + }; + CHECK_FALSE(etl::is_trivially_relocatable::value); + +#if ETL_USING_STL || ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + // These tests require STL or compiler builtins to correctly detect struct/array triviality + CHECK_TRUE(etl::is_trivially_relocatable::value); + CHECK_TRUE(etl::is_trivially_relocatable::value); + CHECK_TRUE(etl::is_trivially_relocatable::value); +#endif + +#if ETL_USING_CPP17 + // Test the _v helper variable + CHECK_TRUE(etl::is_trivially_relocatable_v); + CHECK_TRUE(etl::is_trivially_relocatable_v); + CHECK_TRUE(etl::is_trivially_relocatable_v); + #if ETL_USING_STL || ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + CHECK_TRUE(etl::is_trivially_relocatable_v); + #endif + CHECK_FALSE(etl::is_trivially_relocatable_v); + CHECK_FALSE(etl::is_trivially_relocatable_v); +#endif + + // Verify consistency: if a type is trivially_copyable AND trivially_destructible, + // then it should be trivially_relocatable. The reverse may not hold when compiler + // builtins provide more accurate detection than the fallback implementations. + CHECK_TRUE(!(etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + || etl::is_trivially_relocatable::value); + CHECK_TRUE(!(etl::is_trivially_copyable::value && etl::is_trivially_destructible::value) + || etl::is_trivially_relocatable::value); + // Non-trivially destructible types should never be trivially relocatable + CHECK_FALSE(etl::is_trivially_relocatable::value); + // Non-trivially copyable types should never be trivially relocatable + CHECK_FALSE(etl::is_trivially_relocatable::value); + } + + //************************************************************************* + TEST(test_is_nothrow_relocatable) + { + // Trivially relocatable types should always be nothrow relocatable + // Primitive types should always be detected correctly + CHECK_TRUE(etl::is_nothrow_relocatable::value); + CHECK_TRUE(etl::is_nothrow_relocatable::value); + CHECK_TRUE(etl::is_nothrow_relocatable::value); + CHECK_TRUE(etl::is_nothrow_relocatable::value); + + // POD struct should be nothrow relocatable when proper detection is available + struct TrivialStruct + { + int x; + double y; + }; + +#if ETL_USING_STL || ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + // These tests require STL or compiler builtins to correctly detect struct/array triviality + CHECK_TRUE(etl::is_nothrow_relocatable::value); + CHECK_TRUE(etl::is_nothrow_relocatable::value); + CHECK_TRUE(etl::is_nothrow_relocatable::value); +#endif + +#if ETL_USING_CPP17 + // Test the _v helper variable + CHECK_TRUE(etl::is_nothrow_relocatable_v); + CHECK_TRUE(etl::is_nothrow_relocatable_v); + CHECK_TRUE(etl::is_nothrow_relocatable_v); + #if ETL_USING_STL || ETL_USING_BUILTIN_IS_TRIVIALLY_RELOCATABLE + CHECK_TRUE(etl::is_nothrow_relocatable_v); + #endif +#endif + + // Verify consistency: nothrow_relocatable should be at least as permissive as trivially_relocatable + CHECK_TRUE(!etl::is_trivially_relocatable::value || etl::is_nothrow_relocatable::value); + CHECK_TRUE(!etl::is_trivially_relocatable::value || etl::is_nothrow_relocatable::value); + } + //************************************************************************* TEST(test_is_base_of_any) { diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index f8b8fe5f..1a1410ba 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -2243,6 +2243,131 @@ namespace CHECK(etl::holds_alternative(v1)); CHECK(etl::get_if(&v1) != nullptr); } + + //************************************************************************* + // Tests for noexcept properties of etl::variant + // The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled, + // because ETL_NOEXCEPT_IF expands to nothing otherwise. + // The etl::is_nothrow_* traits only work with STL or builtins. + //************************************************************************* + #if ETL_USING_EXCEPTIONS && (defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS))) + + struct VariantNothrowType + { + VariantNothrowType() noexcept {} + VariantNothrowType(const VariantNothrowType&) noexcept {} + VariantNothrowType(VariantNothrowType&&) noexcept {} + VariantNothrowType& operator=(const VariantNothrowType&) noexcept + { + return *this; + } + VariantNothrowType& operator=(VariantNothrowType&&) noexcept + { + return *this; + } + }; + + struct VariantThrowingCopy + { + VariantThrowingCopy() noexcept {} + VariantThrowingCopy(const VariantThrowingCopy&) {} // may throw + VariantThrowingCopy(VariantThrowingCopy&&) noexcept {} + VariantThrowingCopy& operator=(const VariantThrowingCopy&) + { + return *this; + } + VariantThrowingCopy& operator=(VariantThrowingCopy&&) noexcept + { + return *this; + } + }; + + struct VariantThrowingMove + { + VariantThrowingMove() noexcept {} + VariantThrowingMove(const VariantThrowingMove&) noexcept {} + VariantThrowingMove(VariantThrowingMove&&) {} // may throw + VariantThrowingMove& operator=(const VariantThrowingMove&) noexcept + { + return *this; + } + VariantThrowingMove& operator=(VariantThrowingMove&&) + { + return *this; + } + }; + + TEST(test_variant_nothrow_copy_constructible) + { + // variant is nothrow copy constructible only if all Ts are + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_copy_constructible::value, "variant should be nothrow copy constructible"); + + using HasThrowingCopy = etl::variant; + static_assert(!etl::is_nothrow_copy_constructible::value, + "variant should NOT be nothrow copy constructible"); + + using HasThrowingMove = etl::variant; + static_assert(etl::is_nothrow_copy_constructible::value, + "variant should be nothrow copy constructible (copy is nothrow)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_move_constructible) + { + // variant is nothrow move constructible only if all Ts are + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_move_constructible::value, "variant should be nothrow move constructible"); + + using HasThrowingMove = etl::variant; + static_assert(!etl::is_nothrow_move_constructible::value, + "variant should NOT be nothrow move constructible"); + + using HasThrowingCopy = etl::variant; + static_assert(etl::is_nothrow_move_constructible::value, + "variant should be nothrow move constructible (move is nothrow)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_default_constructible) + { + // variant default-constructs the first alternative + using NothrowFirst = etl::variant; + static_assert(etl::is_nothrow_default_constructible::value, + "variant should be nothrow default constructible (int is nothrow)"); + + using ThrowingFirst = etl::variant; + // VariantThrowingCopy has noexcept default ctor, so this should be nothrow + static_assert(etl::is_nothrow_default_constructible::value, + "variant should be nothrow default constructible (ThrowingCopy has noexcept default ctor)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_copy_assignable) + { + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_copy_assignable::value, "variant should be nothrow copy assignable"); + + using HasThrowingCopy = etl::variant; + static_assert(!etl::is_nothrow_copy_assignable::value, "variant should NOT be nothrow copy assignable"); + + CHECK(true); + } + + TEST(test_variant_nothrow_move_assignable) + { + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_move_assignable::value, "variant should be nothrow move assignable"); + + using HasThrowingMove = etl::variant; + static_assert(!etl::is_nothrow_move_assignable::value, "variant should NOT be nothrow move assignable"); + + CHECK(true); + } + #endif } } // namespace diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 93ea62c4..0e0b6601 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -10273,8 +10273,9 @@ - - + + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 4921e669..8553316d 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3647,7 +3647,7 @@ Tests\Chrono - + Tests\Callbacks & Delegates @@ -3704,7 +3704,7 @@ Tests\CRC - + Tests\Callbacks & Delegates @@ -3800,6 +3800,9 @@ Tests\Strings + + Tests\Callbacks & Delegates + @@ -3979,12 +3982,6 @@ Resource Files\CI\Github - - Documentation - - - Documentation -