diff --git a/.github/setenv.sh b/.github/setenv.sh index a13bcadb..185a65aa 100644 --- a/.github/setenv.sh +++ b/.github/setenv.sh @@ -255,6 +255,34 @@ function c4_cfg_test() if [ ! -z "$CMAKE_FLAGS" ] ; then _addcmkflags $CMAKE_FLAGS fi + # do this before setting CMAKE_C_FLAGS + case "$CXX_" in + vs*) + # WATCHOUT: leave a leading space in the _FLAGS options! + # This is needed because bash will expand a leading + # /DWIN32 to the fs root, ie to something like + # C:/Git/DWIN32. The leading space prevents this. + # + # see https://github.com/bmatzelle/gow/issues/196 + CFLAGS=" /DWIN32 /D_WINDOWS $CFLAGS" + CXXFLAGS=" /DWIN32 /D_WINDOWS /EHsc /GR $CXXFLAGS" + ;; + xcode) ;; + arm*|"") # make sure arm* comes before *g++ or *gcc* + ;; + *g++*|*gcc*|*clang*) + CFLAGS="-std=c99 -m$bits $CFLAGS" + CXXFLAGS="-m$bits $CXXFLAGS" + ;; + em++) + CFLAGS="-s DISABLE_EXCEPTION_CATCHING=0 $CFLAGS" + CXXFLAGS="-s DISABLE_EXCEPTION_CATCHING=0 $CXXFLAGS" + ;; + *) + echo "unknown compiler" + exit 1 + ;; + esac echo "building with additional cmake flags: $CMFLAGS" @@ -273,13 +301,15 @@ function c4_cfg_test() cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ -G 'Visual Studio 17 2022' -A $(_c4vsarchtype $id) \ $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS + -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ + -DCMAKE_C_FLAGS=" $CFLAGS" -DCMAKE_CXX_FLAGS=" $CXXFLAGS" ;; vs2019) cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ -G 'Visual Studio 16 2019' -A $(_c4vsarchtype $id) \ $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS + -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ + -DCMAKE_C_FLAGS=" $CFLAGS" -DCMAKE_CXX_FLAGS=" $CXXFLAGS" ;; vs2017) case "$bits" in @@ -289,7 +319,8 @@ function c4_cfg_test() esac cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" $CMFLAGS + -DCMAKE_BUILD_TYPE=$BT -G "$g" \ + -DCMAKE_C_FLAGS=" $CFLAGS" -DCMAKE_CXX_FLAGS=" $CXXFLAGS" ;; xcode) g=Xcode @@ -301,24 +332,28 @@ function c4_cfg_test() ;; esac cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" -DCMAKE_OSX_ARCHITECTURES=$a $CMFLAGS + -DCMAKE_BUILD_TYPE=$BT -G "$g" \ + -DCMAKE_OSX_ARCHITECTURES=$a $CMFLAGS \ + -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" ;; arm*|"") # make sure arm* comes before *g++ or *gcc* cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS + -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ + -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" ;; *g++*|*gcc*|*clang*) export CC_=$(echo "$CXX_" | sed 's:clang++:clang:g' | sed 's:g++:gcc:g') _c4_choose_clang_tidy $CXX_ cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ -DCMAKE_C_COMPILER=$CC_ -DCMAKE_CXX_COMPILER=$CXX_ \ - -DCMAKE_C_FLAGS="-std=c99 -m$bits" -DCMAKE_CXX_FLAGS="-m$bits" + -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ + -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" cmake --build $build_dir --target help | sed 1d | sort ;; em++) emcmake cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS -DCMAKE_CXX_FLAGS="-s DISABLE_EXCEPTION_CATCHING=0" + -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ + -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" ;; *) echo "unknown compiler" diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index df219488..1fe28d06 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -91,6 +91,46 @@ jobs: - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} + #---------------------------------------------------------------------------- + clang_noexceptions: + name: clang_noexceptions/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} + continue-on-error: true + if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + include: + - {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} + env: {CXXFLAGS: "-fno-exceptions -fno-rtti", STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} + steps: + - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} + - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} + - {name: show info, run: source .github/setenv.sh && c4_show_info} + - name: shared64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared64 + - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} + - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} + - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} + - name: static64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static64 + - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} + - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} + - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} + - name: static32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static32 + - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} + - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} + - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} + - name: shared32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared32 + - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} + - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} + - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} + #---------------------------------------------------------------------------- clang_extended: name: clang_extended/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}}/vg${{matrix.vg}} diff --git a/.github/workflows/gcc.yml b/.github/workflows/gcc.yml index 5398d5f2..af725b9e 100644 --- a/.github/workflows/gcc.yml +++ b/.github/workflows/gcc.yml @@ -95,6 +95,46 @@ jobs: - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} + #---------------------------------------------------------------------------- + gcc_noexceptions: + name: gcc_noexceptions/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} + continue-on-error: true + if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + include: + - {std: 11, cxx: g++-7 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 11, cxx: g++-7 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 20, cxx: g++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} + - {std: 20, cxx: g++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} + env: {CXXFLAGS: "-fno-exceptions -fno-rtti", STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} + steps: + - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} + - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} + - {name: show info, run: source .github/setenv.sh && c4_show_info} + - name: shared64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared64 + - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} + - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} + - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} + - name: static64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static64 + - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} + - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} + - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} + - name: static32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static32 + - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} + - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} + - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} + - name: shared32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared32 + - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} + - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} + - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} + #---------------------------------------------------------------------------- gcc_extended: name: gcc_extended/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}}/vg${{matrix.vg}} diff --git a/.github/workflows/test_install.yml b/.github/workflows/test_install.yml index 7f28e757..14c3e85b 100644 --- a/.github/workflows/test_install.yml +++ b/.github/workflows/test_install.yml @@ -36,32 +36,44 @@ jobs: fail-fast: false matrix: include: - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/linux/Release , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/linux/Debug , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/linux/NoExc , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/linux/libcxx/Release, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_package/linux/libcxx/Debug , sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_package/linux/libcxx/NoExc , sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_package/macos/Release , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/macos/Debug , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/macos/NoExc , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/win/Release , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/win/Debug , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } + - {name: find_package/win/NoExc , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64 -DCMAKE_CXX_FLAGS=' /EHa- /EHs- /EHc /EHr- /GR- /wd4530'", tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } # - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/linux/Release , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/linux/Debug , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/linux/NoExc , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/linux/libcxx/Release, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_library/linux/libcxx/Debug , sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_library/linux/libcxx/NoExc , sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: find_library/macos/Release , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/macos/Debug , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/macos/NoExc , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/win/Release , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/win/Debug , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } + - {name: find_library/win/NoExc , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64 -DCMAKE_CXX_FLAGS=' /EHa- /EHs- /EHc /EHr- /GR- /wd4530'", tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } # - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: , commonvars: } - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: , commonvars: } - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } + - {name: singleheader/linux/Release , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: , commonvars: } + - {name: singleheader/linux/Debug , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: , commonvars: } + - {name: singleheader/linux/NoExc , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: , commonvars: } + - {name: singleheader/linux/libcxx/Release, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: singleheader/linux/libcxx/Debug , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: singleheader/linux/libcxx/NoExc , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: all , bt: Debug , vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} + - {name: singleheader/macos/Release , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: } + - {name: singleheader/macos/Debug , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } + - {name: singleheader/macos/NoExc , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_CXX_FLAGS='-fno-exceptions -fno-rtti'" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } + - {name: singleheader/win/Release , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: } + - {name: singleheader/win/Debug , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } + - {name: singleheader/win/NoExc , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64 -DCMAKE_CXX_FLAGS=' /EHa- /EHs- /EHc /EHr- /GR- /wd4530'", tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } env: CXX_: "${{matrix.cxx}}" BT: "${{matrix.bt}}" diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 11a54f18..463f41eb 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -108,6 +108,48 @@ jobs: - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} + #---------------------------------------------------------------------------- + windows_noexc: + name: win_noexc/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} + continue-on-error: true + if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + include: + - {std: 11, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} + - {std: 11, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} + - {std: 20, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} + - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} + # https://learn.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=msvc-170 + # https://learn.microsoft.com/en-us/cpp/build/reference/gr-enable-run-time-type-information?view=msvc-170 + env: {CXXFLAGS: "/EHa- /EHs- /EHc /EHr- /GR- /wd4530", STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} + steps: + - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} + - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} + - {name: show info, run: source .github/setenv.sh && c4_show_info} + - name: shared64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared64 + - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} + - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} + - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} + - name: static64-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static64 + - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} + - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} + - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} + - name: shared32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test shared32 + - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} + - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} + - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} + - name: static32-configure--------------------------------------------------- + run: source .github/setenv.sh && c4_cfg_test static32 + - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} + - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} + - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} + #---------------------------------------------------------------------------- # TODO how to run? windows_arm: diff --git a/bm/bm_format.cpp b/bm/bm_format.cpp index 64d23cbf..5716883e 100644 --- a/bm/bm_format.cpp +++ b/bm/bm_format.cpp @@ -92,16 +92,24 @@ const c4::csubstr sep = " --- "; //----------------------------------------------------------------------------- namespace dump2str { +static constexpr size_t strsz = 20000000u; std::string c_style_subject; void c_style(c4::csubstr s) { c_style_subject.append(s.str, s.len); } +void reset_c_style() noexcept +{ + c_style_subject.clear(); + c_style_subject.reserve(strsz); +} struct cpp_style { std::string subject = {}; + cpp_style() { subject.reserve(strsz); } void operator() (c4::csubstr s) { subject.append(s.str, s.len); } }; struct lambda_style { std::string subject = {}; + lambda_style() { subject.reserve(strsz); } }; } // namespace dump2str @@ -237,6 +245,7 @@ void cat_c4catrs_no_reuse(bm::State &st) void cat_c4catdump_c_style_static_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::cat(buf, _c4argbundle); @@ -249,6 +258,7 @@ void cat_c4catdump_c_style_static_dispatch(bm::State &st) void cat_c4catdump_c_style_dynamic_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::cat(buf, _c4argbundle); @@ -463,6 +473,7 @@ void catsep_c4catrs_no_reuse(bm::State &st) void catsep_c4catdump_c_style_static_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::catsep(buf, _c4argbundle); @@ -475,6 +486,7 @@ void catsep_c4catdump_c_style_static_dispatch(bm::State &st) void catsep_c4catdump_c_style_dynamic_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::catsep(buf, _c4argbundle); @@ -689,6 +701,7 @@ void format_c4formatrs_no_reuse(bm::State &st) void format_c4formatdump_c_style_static_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); @@ -701,6 +714,7 @@ void format_c4formatdump_c_style_static_dispatch(bm::State &st) void format_c4formatdump_c_style_dynamic_dispatch(bm::State &st) { + dump2str::reset_c_style(); char buf_[256]; c4::substr buf(buf_); size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); diff --git a/bm/float/CMakeLists.txt b/bm/float/CMakeLists.txt index 41234bea..03dc1a7c 100644 --- a/bm/float/CMakeLists.txt +++ b/bm/float/CMakeLists.txt @@ -61,15 +61,17 @@ endif() get_property(known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) if(cxx_std_17 IN_LIST known_features) - c4core_bm_readfloat(fast_fp_f_limited C4FLOAT_FP_F_LIMITED jkj_fp) - c4core_bm_readfloat(fast_fp_d_limited C4FLOAT_FP_D_LIMITED jkj_fp) - c4core_bm_readfloat(fast_fp_f_unlimited C4FLOAT_FP_F_UNLIMITED jkj_fp) - c4core_bm_readfloat(fast_fp_d_unlimited C4FLOAT_FP_D_UNLIMITED jkj_fp) - target_compile_features(c4core-bm-readfloat-fast_fp_f_limited PRIVATE cxx_std_17) - target_compile_features(c4core-bm-readfloat-fast_fp_d_limited PRIVATE cxx_std_17) - target_compile_features(c4core-bm-readfloat-fast_fp_f_unlimited PRIVATE cxx_std_17) - target_compile_features(c4core-bm-readfloat-fast_fp_d_unlimited PRIVATE cxx_std_17) - # incredible - 3 years of C++17 and from_chars()/to_chars() is not available + if(C4CORE_BM_USE_FP) + c4core_bm_readfloat(fast_fp_f_limited C4FLOAT_FP_F_LIMITED jkj_fp) + c4core_bm_readfloat(fast_fp_d_limited C4FLOAT_FP_D_LIMITED jkj_fp) + c4core_bm_readfloat(fast_fp_f_unlimited C4FLOAT_FP_F_UNLIMITED jkj_fp) + c4core_bm_readfloat(fast_fp_d_unlimited C4FLOAT_FP_D_UNLIMITED jkj_fp) + target_compile_features(c4core-bm-readfloat-fast_fp_f_limited PRIVATE cxx_std_17) + target_compile_features(c4core-bm-readfloat-fast_fp_d_limited PRIVATE cxx_std_17) + target_compile_features(c4core-bm-readfloat-fast_fp_f_unlimited PRIVATE cxx_std_17) + target_compile_features(c4core-bm-readfloat-fast_fp_d_unlimited PRIVATE cxx_std_17) + endif() + # incredible - 6 years of C++17 and from_chars()/to_chars() is not available if(NOT ((CMAKE_CXX_COMPILER_ID STREQUAL GNU) OR (CMAKE_CXX_COMPILER_ID STREQUAL Clang))) c4core_bm_readfloat(std_from_chars_f C4FLOAT_STD_FROM_CHARS_F) c4core_bm_readfloat(std_from_chars_d C4FLOAT_STD_FROM_CHARS_D) diff --git a/changelog/current.md b/changelog/current.md index 327eaa37..2fb3b801 100644 --- a/changelog/current.md +++ b/changelog/current.md @@ -1,5 +1,19 @@ +### New features -=== Fixes === +- [PR#105](https://github.com/biojppm/c4core/pull/105): Add macros in `c4/language.hpp` for compile-time flow of exceptions: + - `C4_EXCEPTIONS`: defined when exceptions are enabled + - `C4_IF_EXCEPTIONS(code_with_exc, code_without_exc)`: select statements for exceptions enabled/disabled + - `C4_IF_EXCEPTIONS_(code_with_exc, code_without_exc)`: select code tokens for exceptions enabled/disabled +- [PR#105](https://github.com/biojppm/c4core/pull/105): Add macros in `c4/language.hpp` for compile-time flow of RTTI: + - `C4_RTTI`: defined when rtti is enabled + - `C4_IF_RTTI(code_with_rtti, code_without_rtti)`: select statements for rtti enabled/disabled + - `C4_IF_RTTI_(code_with_rtti, code_without_rtti)`: select code tokens for rtti enabled/disabled -* [PR#104](https://github.com/biojppm/c4core/pull/104) - Fix pedantic warnings in gcc, clang and MSVC -* [PR#104](https://github.com/biojppm/c4core/pull/104) - Fix possible compile error when `__GNUC__` is not defined + +### Fixes + +- [PR#107](https://github.com/biojppm/c4core/pull/107) - Update fast_float. +- [PR#106](https://github.com/biojppm/c4core/pull/106) - Fix include guard in the gcc 4.8 compatibility header, causing it to be missing from the amalgamated header. +- [PR#105](https://github.com/biojppm/c4core/pull/105) - Fix existing throw in `c4/ext/sg14/inplace_function.h`. Ensure tests run with exceptions disabled and RTTI disabled. Add examples of exceptional control flow with `setjmp()/std::longjmp()`. +- [PR#104](https://github.com/biojppm/c4core/pull/104) - Fix pedantic warnings in gcc, clang and MSVC +- [PR#104](https://github.com/biojppm/c4core/pull/104) - Fix possible compile error when `__GNUC__` is not defined diff --git a/src/c4/ext/sg14/inplace_function.h b/src/c4/ext/sg14/inplace_function.h index af3e8305..8d7a5b45 100644 --- a/src/c4/ext/sg14/inplace_function.h +++ b/src/c4/ext/sg14/inplace_function.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace stdext { @@ -81,7 +82,15 @@ template struct vtable explicit constexpr vtable() noexcept : invoke_ptr{ [](storage_ptr_t, Args&&...) -> R - { throw std::bad_function_call(); } + { + #if (defined(_MSC_VER) && (defined(_CPPUNWIND) && (__CPPUNWIND == 1))) \ + || \ + (defined(__EXCEPTIONS) || defined(__cpp_exceptions)) + throw std::bad_function_call(); + #else + std::abort(); + #endif + } }, copy_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} }, move_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} }, diff --git a/src/c4/language.hpp b/src/c4/language.hpp index 90ff9bab..3695588b 100644 --- a/src/c4/language.hpp +++ b/src/c4/language.hpp @@ -149,6 +149,42 @@ #define C4_INLINE_CONSTEXPR inline constexpr #endif +#ifdef _MSC_VER +# if (defined(_CPPUNWIND) && (__CPPUNWIND == 1)) +# define C4_EXCEPTIONS +# endif +#else +# if defined(__EXCEPTIONS) || defined(__cpp_exceptions) +# define C4_EXCEPTIONS +# endif +#endif + +#ifdef C4_EXCEPTIONS +# define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) exc_code +# define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { exc_code } while(0) +#else +# define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) setjmp_code +# define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { setjmp_code } while(0) +#endif + +#ifdef _MSC_VER +# if defined(_CPPRTTI) +# define C4_RTTI +# endif +#else +# if defined(__GXX_RTTI) +# define C4_RTTI +# endif +#endif + +#ifdef C4_RTTI +# define C4_IF_RTTI_(code_rtti, code_no_rtti) code_rtti +# define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_rtti } while(0) +#else +# define C4_IF_RTTI_(code_rtti, code_no_rtti) code_no_rtti +# define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_no_rtti } while(0) +#endif + //------------------------------------------------------------ diff --git a/test/c4/test.hpp b/test/c4/test.hpp index 936283a2..4b54ce4b 100644 --- a/test/c4/test.hpp +++ b/test/c4/test.hpp @@ -19,6 +19,59 @@ #define DOCTEST_CONFIG_SUPER_FAST_ASSERTS #include +// doctest does not provide these macros when exceptions are disabled +// see https://github.com/doctest/doctest/issues/439 +#if !defined(C4_EXCEPTIONS) +# ifndef _MSC_VER +# ifndef DOCTEST_REQUIRE +# define _C4_DEFINE_DOCTEST_REQUIRE +# endif +# else +# define _C4_DEFINE_DOCTEST_REQUIRE +# endif +# ifdef _C4_DEFINE_DOCTEST_REQUIRE +# undef DOCTEST_REQUIRE +# undef REQUIRE +# undef DOCTEST_REQUIRE_TRUE +# undef REQUIRE_TRUE +# undef DOCTEST_REQUIRE_FALSE +# undef REQUIRE_FALSE +# undef DOCTEST_REQUIRE_EQ +# undef REQUIRE_EQ +# undef DOCTEST_REQUIRE_NE +# undef REQUIRE_NE +# undef DOCTEST_REQUIRE_GE +# undef REQUIRE_GE +# undef DOCTEST_REQUIRE_LE +# undef REQUIRE_LE +# undef DOCTEST_REQUIRE_GT +# undef REQUIRE_GT +# undef DOCTEST_REQUIRE_LT +# undef REQUIRE_LT +# define _DOCTEST_FAIL_IF_NOT1(cond) if(cond) {} else { std::abort(); } +# define _DOCTEST_FAIL_IF_NOT2(lhs, op, rhs) if((lhs) op (rhs)) {} else { std::abort(); } +# define _DOCTEST_REQUIRE2(id, lhs, op, rhs) do { CHECK##id(lhs, rhs); _DOCTEST_FAIL_IF_NOT2(lhs, op, rhs) } while(0) +# define DOCTEST_REQUIRE(cond) do { CHECK(cond); _DOCTEST_FAIL_IF_NOT1(cond) } while(0) +# define REQUIRE(cond) do { CHECK(cond); _DOCTEST_FAIL_IF_NOT1(cond) } while(0) +# define DOCTEST_REQUIRE_TRUE(cond) do { CHECK(cond); _DOCTEST_FAIL_IF_NOT1(cond) } while(0) +# define REQUIRE_TRUE(cond) do { CHECK(cond); _DOCTEST_FAIL_IF_NOT1(cond) } while(0) +# define DOCTEST_REQUIRE_FALSE(cond) do { CHECK_FALSE(cond); _DOCTEST_FAIL_IF_NOT1(!(cond)) } while(0) +# define REQUIRE_FALSE(cond) do { CHECK_FALSE(cond); _DOCTEST_FAIL_IF_NOT1(!(cond)) } while(0) +# define DOCTEST_REQUIRE_EQ(lhs, rhs) _DOCTEST_REQUIRE2(_EQ, lhs, ==, rhs) +# define REQUIRE_EQ(lhs, rhs) _DOCTEST_REQUIRE2(_EQ, lhs, ==, rhs) +# define DOCTEST_REQUIRE_NE(lhs, rhs) _DOCTEST_REQUIRE2(_NE, lhs, !=, rhs) +# define REQUIRE_NE(lhs, rhs) _DOCTEST_REQUIRE2(_NE, lhs, !=, rhs) +# define DOCTEST_REQUIRE_GE(lhs, rhs) _DOCTEST_REQUIRE2(_GE, lhs, >=, rhs) +# define REQUIRE_GE(lhs, rhs) _DOCTEST_REQUIRE2(_GE, lhs, >=, rhs) +# define DOCTEST_REQUIRE_LE(lhs, rhs) _DOCTEST_REQUIRE2(_LE, lhs, <=, rhs) +# define REQUIRE_LE(lhs, rhs) _DOCTEST_REQUIRE2(_LE, lhs, <=, rhs) +# define DOCTEST_REQUIRE_GT(lhs, rhs) _DOCTEST_REQUIRE2(_GT, lhs, > , rhs) +# define REQUIRE_GT(lhs, rhs) _DOCTEST_REQUIRE2(_GT, lhs, > , rhs) +# define DOCTEST_REQUIRE_LT(lhs, rhs) _DOCTEST_REQUIRE2(_LT, lhs, < , rhs) +# define REQUIRE_LT(lhs, rhs) _DOCTEST_REQUIRE2(_LT, lhs, < , rhs) +# endif +#endif + #define CHECK_STREQ(lhs, rhs) CHECK_EQ(c4::to_csubstr(lhs), c4::to_csubstr(rhs)) #define CHECK_FLOAT_EQ(lhs, rhs) CHECK((double)(lhs) == doctest::Approx((double)(rhs))) diff --git a/test/test_allocator.cpp b/test/test_allocator.cpp index 78d0daf8..db236f6f 100644 --- a/test/test_allocator.cpp +++ b/test/test_allocator.cpp @@ -94,17 +94,30 @@ TEST_CASE("small_allocator_mr_linear_arr.traits_compat_construct") //----------------------------------------------------------------------------- -template< class Alloc > -void clear_mr(Alloc a) +template +struct clear_mr +{ + template + static void clear(Alloc) + { + //std::cout << C4_PRETTY_FUNC << "\n"; std::cout.flush(); + } +}; + +template<> +struct clear_mr { - auto mrl = dynamic_cast(a.resource()); - if(mrl) + template + static void clear(Alloc a) { + //std::cout << C4_PRETTY_FUNC << "\n"; std::cout.flush(); + MemoryResourceLinear* mrl = static_cast(a.resource()); mrl->clear(); } -} +}; -template< class Alloc > + +template void do_std_containers_test(Alloc alloc) { _c4definealloctypes(Alloc); @@ -116,7 +129,7 @@ void do_std_containers_test(Alloc alloc) CHECK_EQ(v, "adskjhsdfkjdflkjsdfkjhsdfkjh"); } - clear_mr(alloc); + clear_mr::clear(alloc); { int arr[128]; @@ -131,7 +144,7 @@ void do_std_containers_test(Alloc alloc) } } - clear_mr(alloc); + clear_mr::clear(alloc); { AllocChar a = alloc; @@ -144,7 +157,7 @@ void do_std_containers_test(Alloc alloc) CHECK_EQ(v[4], "bax"); } - clear_mr(alloc); + clear_mr::clear(alloc); { AllocString a = alloc; @@ -158,7 +171,7 @@ void do_std_containers_test(Alloc alloc) } } - clear_mr(alloc); + clear_mr::clear(alloc); { #if !defined(__GNUC__) || (__GNUC__ >= 5) @@ -179,12 +192,14 @@ void do_std_containers_test(Alloc alloc) CHECK_EQ(v["baz"], 2); CHECK_EQ(v["bat"], 3); } + + clear_mr::clear(alloc); } TEST_CASE("allocator_global.std_containers") { allocator a; - do_std_containers_test(a); + do_std_containers_test(a); } TEST_CASE("small_allocator_global.std_containers") @@ -198,28 +213,28 @@ TEST_CASE("small_allocator_global.std_containers") TEST_CASE("allocator_mr_global.std_containers") { allocator_mr a; - do_std_containers_test(a); + do_std_containers_test(a); } TEST_CASE("allocator_mr_linear.std_containers") { MemoryResourceLinear mr(1024); allocator_mr a(&mr); - do_std_containers_test(a); + do_std_containers_test(a); } TEST_CASE("allocator_mr_linear_arr.std_containers") { MemoryResourceLinearArr<1024> mr; allocator_mr a(&mr); - do_std_containers_test(a); + do_std_containers_test(a); } TEST_CASE("small_allocator_mr_global.std_containers") { /* this is failing, investigate small_allocator_mr a; - do_std_containers_test(a); + do_std_containers_test(a); */ } @@ -228,7 +243,7 @@ TEST_CASE("small_allocator_mr_linear.std_containers") /* this is failing, investigate MemoryResourceLinear mr(1024); small_allocator_mr a(&mr); - do_std_containers_test(a); + do_std_containers_test(a); */ } @@ -237,7 +252,7 @@ TEST_CASE("small_allocator_mr_linear_arr.std_containers") /* this is failing, investigate MemoryResourceLinearArr<1024> mr; small_allocator_mr a(&mr); - do_std_containers_test(a); + do_std_containers_test(a); */ } diff --git a/test/test_charconv.cpp b/test/test_charconv.cpp index baa840d1..160aa4ff 100644 --- a/test/test_charconv.cpp +++ b/test/test_charconv.cpp @@ -130,6 +130,7 @@ number_case const& front(size_t skip=0) template number_case const& back(size_t skip=0) { + static_assert(std::is_array::vals)>::value, "must be array"); return *(numbers::vals + C4_COUNTOF(numbers::vals) - 1 - skip); } @@ -1657,6 +1658,7 @@ TEST_CASE_TEMPLATE("atox.overflow", T, int8_t, uint8_t, int16_t, uint16_t, int32 } } }; + C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4296) // '>=': expression is always true auto do_test_overflow = [&](T exceed_how_much, T radix){ REQUIRE(exceed_how_much >= 0); number_case const& backelm = back(); @@ -1671,6 +1673,7 @@ TEST_CASE_TEMPLATE("atox.overflow", T, int8_t, uint8_t, int16_t, uint16_t, int32 csubstr exceeded = underflow_by(buf, frntelm.val, exceed_how_much, radix); do_test(exceed_how_much > 0, frntelm, exceeded, wrapelm); }; + C4_SUPPRESS_WARNING_MSVC_POP SUBCASE("zeroes") { test_no_overflow_zeroes(); diff --git a/test/test_error.cpp b/test/test_error.cpp index 96584ab9..e6e94c50 100644 --- a/test/test_error.cpp +++ b/test/test_error.cpp @@ -4,6 +4,10 @@ #include "c4/test.hpp" #include "c4/libtest/supprwarn_push.hpp" +#ifndef C4_EXCEPTIONS +#include +#endif +C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4611) // interaction between '_setjmp' and C++ object destruction is non-portable C4_BEGIN_HIDDEN_NAMESPACE bool got_an_error = false; @@ -58,6 +62,8 @@ TEST_CASE("Error.outside_of_c4_namespace") #include // temporary; just for the exception example #include // temporary; just for the exception example +C4_IF_EXCEPTIONS_( , static std::jmp_buf s_jmp_buf; static std::string s_jmp_errmsg; ); + namespace c4 { #define C4_ERR_FMT_BUFFER_SIZE 256 @@ -237,7 +243,7 @@ TEST_CASE("ErrorBehaviorAbort.default_obj") void fputi(int val, FILE *f); void _append(std::string *s, int line); -/** example implementation using vanilla c++ std::runtime_error */ +/** example implementation using vanilla c++ std::runtime_error (or setjmp when exceptions are disabled) */ struct ErrorBehaviorRuntimeError : public ErrorCallbacksBridgeFull { std::string exc_msg{}; @@ -261,10 +267,11 @@ struct ErrorBehaviorRuntimeError : public ErrorCallbacksBridgeFull void test_error_fmt_exception(const char (&expected)[M], const char (&fmt)[N], Args const& ...args) { - INFO(expected); + INFO("expected is: '" << expected << "'"); { auto tmp1 = C4_TMP_ERR_BHV(ErrorBehaviorAbort); { auto tmp2 = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); - bool got_exc = false; - try { - C4_ERROR_FMT_NEW(fmt, args...); - } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(M-1); - CHECK_EQ(what, expected); - got_exc = (what == expected); + { + bool got_exc = false; + C4_IF_EXCEPTIONS_(try, if(setjmp(s_jmp_buf) == 0)) + { + c4::err_fmt(C4_SRCLOC(), fmt, args...); + } + C4_IF_EXCEPTIONS_(catch(std::exception const& e), else) + { + // check that the given message is found verbatim on the error message + c4::csubstr errmsg = c4::to_csubstr(C4_IF_EXCEPTIONS_(e.what(), s_jmp_errmsg.c_str())); + INFO("full message: '''" << errmsg << "'''"); + size_t pos = errmsg.find(expected); + CHECK_NE(pos, c4::csubstr::npos); + got_exc = (pos != c4::csubstr::npos); + } + CHECK(got_exc); } - CHECK(got_exc); - got_exc = false; - try { - C4_ERROR_FMT_NEW_SZ(fmt, N-1, args...); + { + bool got_exc = false; + C4_IF_EXCEPTIONS_(try, if(setjmp(s_jmp_buf) == 0)) + { + c4 ::err_fmt(C4_SRCLOC(), N - 1, fmt, args...); + } + C4_IF_EXCEPTIONS_(catch(std::exception const& e), else) + { + // check that the given message is found verbatim on the error message + c4::csubstr errmsg = c4::to_csubstr(C4_IF_EXCEPTIONS_(e.what(), s_jmp_errmsg.c_str())); + INFO("full message: '''" << errmsg << "'''"); + size_t pos = errmsg.find(expected); + CHECK_NE(pos, c4::csubstr::npos); + got_exc = (pos != c4::csubstr::npos); + } + CHECK(got_exc); } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(M-1); - CHECK_EQ(what, expected); - got_exc = (what == expected); - } - CHECK(got_exc); } } } @@ -593,13 +618,13 @@ void test_warning_fmt_exception(const char (&expected)[M], const char (&fmt)[N], auto tmp = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); auto const& wmsg = tmp.m_tmp.exc_msg; - C4_WARNING_FMT_NEW(fmt, args...); + c4 ::warn_fmt(C4_SRCLOC(), fmt, args...); REQUIRE_FALSE(wmsg.empty()); REQUIRE_GT(wmsg.size(), M); auto what = c4::to_csubstr(wmsg.c_str()).last(M-1); CHECK_EQ(what, expected); - C4_WARNING_FMT_NEW_SZ(fmt, N-1, args...); + c4 ::warn_fmt(C4_SRCLOC(), N - 1, fmt, args...); REQUIRE_FALSE(wmsg.empty()); REQUIRE_GT(wmsg.size(), M); what = c4::to_csubstr(wmsg.c_str()).last(M-1); @@ -609,27 +634,29 @@ void test_warning_fmt_exception(const char (&expected)[M], const char (&fmt)[N], TEST_CASE("error.fmt") { - test_error_fmt_exception("aaa is 2 is it not?", - "{} is {} is it not?", "aaa", 2); - test_error_fmt_exception("aaa is bbb is it not?", - "{} is {} is it not?", "aaa", "bbb"); - test_error_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); - test_error_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); + test_error_fmt_exception("abc is 2 is it not?", + "{} is {} is it not?", "abc", 2); + test_error_fmt_exception("abc is bbb is it not?", + "{} is {} is it not?", "abc", "bbb"); + test_error_fmt_exception("abc is {} is it not?", + "{} is {} is it not?", "abc"); + test_error_fmt_exception("abc is {} is it not?", + "{} is {} is it not?", "abc"); } TEST_CASE("warning.fmt") { - test_warning_fmt_exception("aaa is 2 is it not?", - "{} is {} is it not?", "aaa", 2); - test_warning_fmt_exception("aaa is bbb is it not?", - "{} is {} is it not?", "aaa", "bbb"); - test_warning_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); - test_warning_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); + test_warning_fmt_exception("abc is 2 is it not?", + "{} is {} is it not?", "abc", 2); + test_warning_fmt_exception("abc is bbb is it not?", + "{} is {} is it not?", "abc", "bbb"); + test_warning_fmt_exception("abc is {} is it not?", + "{} is {} is it not?", "abc"); + test_warning_fmt_exception("abc is {} is it not?", + "{} is {} is it not?", "abc"); } +C4_SUPPRESS_WARNING_MSVC_POP + #include "c4/libtest/supprwarn_pop.hpp" diff --git a/test/test_error_exception.cpp b/test/test_error_exception.cpp index fae0020b..0d8812af 100644 --- a/test/test_error_exception.cpp +++ b/test/test_error_exception.cpp @@ -4,23 +4,34 @@ #include "c4/test.hpp" #include +#ifdef C4_EXCEPTIONS #include - +#else +#include +#endif +C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4611) // interaction between '_setjmp' and C++ object destruction is non-portable C4_BEGIN_HIDDEN_NAMESPACE bool got_an_error = false; bool got_an_exception = false; +C4_IF_EXCEPTIONS_( , std::jmp_buf s_jmp_env; int s_jmp_val; std::string s_jmp_msg;) C4_END_HIDDEN_NAMESPACE void error_callback_throwing_exception(const char *msg_, size_t msg_sz) { got_an_error = true; c4::csubstr s(msg_, msg_sz); - if (s == "err1") throw 1; - else if(s == "err2") throw 2; - else if(s == "err3") throw 3; - else if(s == "err4") throw 4; - else throw std::runtime_error({msg_, msg_+msg_sz}); + if (s == "err1") C4_IF_EXCEPTIONS(throw 1; , s_jmp_val = 1; std::longjmp(s_jmp_env, s_jmp_val);); + else if(s == "err2") C4_IF_EXCEPTIONS(throw 2; , s_jmp_val = 2; std::longjmp(s_jmp_env, s_jmp_val);); + else if(s == "err3") C4_IF_EXCEPTIONS(throw 3; , s_jmp_val = 3; std::longjmp(s_jmp_env, s_jmp_val);); + else if(s == "err4") C4_IF_EXCEPTIONS(throw 4; , s_jmp_val = 4; std::longjmp(s_jmp_env, s_jmp_val);); + else C4_IF_EXCEPTIONS( + throw std::runtime_error({msg_, msg_+msg_sz}); + , + s_jmp_val = 100; + s_jmp_msg.assign(msg_, msg_sz); + std::longjmp(s_jmp_env, s_jmp_val); + ); } inline c4::ScopedErrorSettings tmp_err() @@ -29,17 +40,20 @@ inline c4::ScopedErrorSettings tmp_err() return c4::ScopedErrorSettings(c4::ON_ERROR_CALLBACK, error_callback_throwing_exception); } +C4_IF_EXCEPTIONS_( , std::jmp_buf s_jmp_env_fwd;) -void test_exception(int which) +void test_exception(const int which) { - if(which == 0) return; - CHECK_FALSE(got_an_exception); - CHECK_EQ(c4::get_error_callback() == error_callback_throwing_exception, false); + if(which == 0) + return; + INFO("which=" << which); + C4_CHECK(!got_an_exception); + C4_CHECK(c4::get_error_callback() == error_callback_throwing_exception); { auto tmp = tmp_err(); CHECK_EQ(got_an_error, false); CHECK_EQ(c4::get_error_callback() == error_callback_throwing_exception, true); - try + C4_IF_EXCEPTIONS_(try, if(setjmp(s_jmp_env) == 0)) { if (which == 1) { C4_ERROR("err1"); } else if(which == 2) { C4_ERROR("err2"); } @@ -47,19 +61,22 @@ void test_exception(int which) else if(which == 4) { C4_ERROR("err4"); } else { C4_ERROR("unknown error"); } } - catch(int i) + C4_IF_EXCEPTIONS_(catch(int i), else if(s_jmp_val < 5)) { got_an_exception = true; CHECK_EQ(got_an_error, true); - CHECK_EQ(i, which); - throw; + CHECK_EQ(C4_IF_EXCEPTIONS_(i, s_jmp_val), which); + C4_IF_EXCEPTIONS_(throw, std::longjmp(s_jmp_env_fwd, s_jmp_val)); } - catch(std::runtime_error const& e) + C4_IF_EXCEPTIONS_(catch(std::runtime_error const& e), else) { got_an_exception = true; CHECK_EQ(got_an_error, true); - CHECK_STREQ(e.what(), "unknown error"); - throw; + const c4::csubstr expected = "unknown error"; + const c4::csubstr actual = C4_IF_EXCEPTIONS_(c4::to_csubstr(e.what()), c4::csubstr(s_jmp_msg.data(), s_jmp_msg.size())); + CHECK_EQ(actual.size(), expected.size()); + CHECK_EQ(actual, expected); + C4_IF_EXCEPTIONS_(throw, std::longjmp(s_jmp_env_fwd, s_jmp_val)); } // if we get here it means no exception was thrown // so the test failed @@ -69,40 +86,45 @@ void test_exception(int which) } -// Although c4core does not use exceptions by default (*), you can have your -// error callback throw an exception which you can then catch on your code. -// This test covers that possibility. +// Although c4core does not use exceptions by default, you can have +// your error callback throw an exception which you can then catch on +// your code. // -// (*) Note that you can also configure c4core to throw an exception on error. +// This test covers that possibility. TEST_CASE("error.exception_from_callback") { // works! - got_an_exception = false; - CHECK_THROWS_AS(test_exception(-1), std::runtime_error); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_NOTHROW(test_exception(0)); - CHECK_FALSE(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(1), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(2), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(3), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(4), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(6), std::runtime_error); - CHECK(got_an_exception); + auto tmp = tmp_err(); + + #ifdef C4_EXCEPTIONS + #define CHECK_FAILURE_IS(code, failure_exc, failure_setjmp) \ + { \ + got_an_exception = false; \ + CHECK_THROWS_AS(code, failure_exc); \ + CHECK(got_an_exception); \ + } + #else + #define CHECK_FAILURE_IS(code, failure_exc, failure_setjmp) \ + { \ + INFO("expected case: " << failure_setjmp); \ + got_an_exception = false; \ + if(setjmp(s_jmp_env_fwd) == 0) \ + { \ + code; \ + } \ + CHECK_EQ(s_jmp_val, failure_setjmp); \ + CHECK(got_an_exception); \ + } + #endif + + CHECK_FAILURE_IS(test_exception(-1), std::runtime_error, 100); + CHECK_FAILURE_IS(test_exception(1), int, 1); + CHECK_FAILURE_IS(test_exception(2), int, 2); + CHECK_FAILURE_IS(test_exception(3), int, 3); + CHECK_FAILURE_IS(test_exception(4), int, 4); + CHECK_FAILURE_IS(test_exception(5), std::runtime_error, 100); + CHECK_FAILURE_IS(test_exception(6), std::runtime_error, 100); } + +C4_SUPPRESS_WARNING_MSVC_POP