catchorg / Catch2

A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)
https://discord.gg/4CWS9zD
Boost Software License 1.0
18.68k stars 3.05k forks source link

riscv: build failure due to Werror=cast-align #2808

Open skeuchel opened 9 months ago

skeuchel commented 9 months ago

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::stored_object() [with T = std::__cxx11::basic_string; bool Destruct = false]': 36.35 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t Catch::Benchmark::Detail::ObjectStorage::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string; bool Destruct = false; std::enable_if_t = 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*' increases required alignment of target type [-Werror=cast-align] 36.35 61 | T& stored_object() { return *reinterpret_cast( data ); } 36.35 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp: In instantiation of 'T& Catch::Benchmark::Detail::ObjectStorage::stored_object() [with T = std::__cxx11::basic_string; bool Destruct = true]': 36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:46:34: required from 'std::enable_if_t Catch::Benchmark::Detail::ObjectStorage::destruct() [with bool AllowManualDestruction = true; T = std::__cxx11::basic_string; bool Destruct = true; std::enable_if_t = void]' 36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:52:97: required from 'void Catch::Benchmark::Detail::ObjectStorage::destruct_on_exit(std::enable_if_t*) [with U = std::__cxx11::basic_string; T = std::__cxx11::basic_string; bool Destruct = true; std::enable_if_t = std::__cxx11::basic_string]' 36.39 /catch2/src/catch2/../catch2/benchmark/catch_constructor.hpp:35:55: required from 'Catch::Benchmark::Detail::ObjectStorage::~ObjectStorage() [with T = std::__cxx11::basic_string; 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, true>]' 36.39 /usr/riscv64-linux-gnu/include/c++/13/bits/stl_construct.h:163:19: required from 'static void std::_Destroy_aux< >::__destroy(_ForwardIterator, _ForwardIterator) [with _ForwardIterator = Catch::Benchmark::Detail::ObjectStorage, true>*; bool = 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, 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, true>*; _Tp = Catch::Benchmark::Detail::ObjectStorage<__cxx11::basic_string, 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, true>; _Alloc = std::allocator, 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*' 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:

Additional context Not sure if catch or gcc is to blame.

misuzu commented 8 months ago

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;;]
``
p4vook commented 7 months ago

I think this could be fixed by setting the alignment of data to alignas(T, T*)