Catch2
Catch2 copied to clipboard
riscv: build failure due to Werror=cast-align
Describe the bug When building for the riscv64 architecture, a build failure occurs in the test suite due to treating warnings as errors.
build log snippet
36.07 [ 85%] Building CXX object tests/CMakeFiles/SelfTest.dir/SelfTest/UsageTests/Benchmark.tests.cpp.o
36.35 In file included from /catch2/tests/SelfTest/UsageTests/Benchmark.tests.cpp:12:
36.35 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp: In instantiation of 'T& Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::stored_object() [with T = std::__cxx11::basic_string<char>; bool Destruct = false]':
36.35 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t<AllowManualDestruction> Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string<char>; bool Destruct = false; std::enable_if_t<AllowManualDestruction> = void]'
36.35 /catch2/tests/SelfTest/UsageTests/Benchmark.tests.cpp:153:59: required from here
36.35 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:61:46: error: cast from 'unsigned char*' to 'std::__cxx11::basic_string<char>*' increases required alignment of target type [-Werror=cast-align]
36.35 61 | T& stored_object() { return *reinterpret_cast<T*>( data ); }
36.35 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp: In instantiation of 'T& Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::stored_object() [with T = std::__cxx11::basic_string<char>; bool Destruct = true]':
36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t<AllowManualDestruction> Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string<char>; bool Destruct = true; std::enable_if_t<AllowManualDestruction> = void]'
36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:52:97: required from 'void Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct_on_exit(std::enable_if_t<Destruct, U>*) [with U = std::__cxx11::basic_string<char>; T = std::__cxx11::basic_string<char>; bool Destruct = true; std::enable_if_t<Destruct, U> = std::__cxx11::basic_string<char>]'
36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:35:55: required from 'Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::~ObjectStorage() [with T = std::__cxx11::basic_string<char>; bool Destruct = true]'
36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/stl_construct.h:151:22: required from 'constexpr void std::_Destroy(_Tp*) [with _Tp = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>]'
36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/stl_construct.h:163:19: required from 'static void std::_Destroy_aux<<anonymous> >::__destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true>*; bool <anonymous> = false]'
36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/stl_construct.h:196:11: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>*]'
36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/alloc_traits.h:948:20: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator, allocator<_T2>&) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>*; _Tp = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>]'
36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/stl_vector.h:732:15: required from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true>; _Alloc = std::allocator<Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true> >]'
36.39 /catch2/tests/SelfTest/UsageTests/Benchmark.tests.cpp:145:89: required from here
36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:61:46: error: cast from 'unsigned char*' to 'std::__cxx11::basic_string<char>*' increases required alignment of target type [-Werror=cast-align]
36.69 cc1plus: all warnings being treated as errors
Expected behavior A successful build.
Reproduction steps It is possible to reproduce the build failure by cross-compiling, so no risc-v hardware is needed. You can build the following docker file on a x64 host to reproduce the build failure.
Dockerfile
FROM debian:trixie
RUN apt-get update && apt-get install -yq cmake g++-riscv64-linux-gnu git python3
RUN git clone --depth=1 https://github.com/catchorg/Catch2.git /catch2
ENV AR="riscv64-linux-gnu-ar"
ENV AS="riscv64-linux-gnu-as"
ENV CC="riscv64-linux-gnu-gcc"
ENV CXX="riscv64-linux-gnu-g++"
ENV LD="riscv64-linux-gnu-ld"
ENV NM="riscv64-linux-gnu-nm"
ENV OBJCOPY="riscv64-linux-gnu-objcopy"
ENV OBJDUMP="riscv64-linux-gnu-objdump"
ENV RANLIB="riscv64-linux-gnu-ranlib"
ENV READELF="riscv64-linux-gnu-readelf"
ENV SIZE="riscv64-linux-gnu-size"
ENV STRINGS="riscv64-linux-gnu-strings"
ENV STRIP="riscv64-linux-gnu-strip"
WORKDIR /build
RUN cmake -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_TESTING=ON \
-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=riscv64 \
-DCMAKE_HOST_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_PROCESSOR=x86_64 \
../catch2
RUN make -j$(nproc)
Platform information:
- OS: NixOS 24.05
- Compiler+version: GCC v13.2.0
- Catch version: v3.5.2
Additional context Not sure if catch or gcc is to blame.
I've the same issue on armv7l-linux
catch2> [ 85%] Building CXX object tests/CMakeFiles/SelfTest.dir/SelfTest/UsageTests/Benchmark.tests.cpp.o
catch2> In file included from /build/source/tests/SelfTest/UsageTests/Benchmark.tests.cpp:12:
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp: In instantiation of 'T& Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::stored_object() [with T = std::__cxx11::basic_string<char>; bool Destruct = false]':
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t<AllowManualDestruction> Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string<char>; bool Destruct = false; std::enable_if_t<AllowManualDestruction> = void]'
catch2> /build/source/tests/SelfTest/UsageTests/Benchmark.tests.cpp:153:59: required from here
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:61:46: error: cast from 'unsigned char*' to 'std::__cxx11::basic_string<char>*' increases required alignment of target type [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wcast-align-Werror=cast-align8;;]
catch2> 61 | T& stored_object() { return *reinterpret_cast<T*>( data ); }
catch2> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp: In instantiation of 'T& Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::stored_object() [with T = std::__cxx11::basic_string<char>; bool Destruct = true]':
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t<AllowManualDestruction> Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string<char>; bool Destruct = true; std::enable_if_t<AllowManualDestruction> = void]'
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:52:97: required from 'void Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::destruct_on_exit(std::enable_if_t<Destruct, U>*) [with U = std::__cxx11::basic_string<char>; T = std::__cxx11::basic_string<char>; bool Destruct = true; std::enable_if_t<Destruct, U> = std::__cxx11::basic_string<char>]'
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:35:55: required from 'Catch::Benchmark::Detail::ObjectStorage<T, Destruct>::~ObjectStorage() [with T = std::__cxx11::basic_string<char>; bool Destruct = true]'
catch2> /nix/store/spipxxlrlpxn3981gjv7mkxjabwdw4z7-gcc-13.2.0/include/c++/13.2.0/bits/stl_construct.h:151:22: required from 'constexpr void std::_Destroy(_Tp*) [with _Tp = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>]'
catch2> /nix/store/spipxxlrlpxn3981gjv7mkxjabwdw4z7-gcc-13.2.0/include/c++/13.2.0/bits/stl_construct.h:163:19: required from 'static void std::_Destroy_aux<<anonymous> >::__destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true>*; bool <anonymous> = false]'
catch2> /nix/store/spipxxlrlpxn3981gjv7mkxjabwdw4z7-gcc-13.2.0/include/c++/13.2.0/bits/stl_construct.h:196:11: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>*]'
catch2> /nix/store/spipxxlrlpxn3981gjv7mkxjabwdw4z7-gcc-13.2.0/include/c++/13.2.0/bits/alloc_traits.h:947:20: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator, allocator<_T2>&) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>*; _Tp = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string<char>, true>]'
catch2> /nix/store/spipxxlrlpxn3981gjv7mkxjabwdw4z7-gcc-13.2.0/include/c++/13.2.0/bits/stl_vector.h:732:15: required from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true>; _Alloc = std::allocator<Catch::Benchmark::Detail::ObjectStorage<std::__cxx11::basic_string<char>, true> >]'
catch2> /build/source/tests/SelfTest/UsageTests/Benchmark.tests.cpp:145:89: required from here
catch2> /build/source/src/catch2/../catch2/benchmark/catch_constructor.hpp:61:46: error: cast from 'unsigned char*' to 'std::__cxx11::basic_string<char>*' increases required alignment of target type [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wcast-align-Werror=cast-align8;;]
``
I think this could be fixed by setting the alignment of data
to alignas(T, T*)