mapbox / variant

C++11/C++14 Variant
BSD 3-Clause "New" or "Revised" License
371 stars 100 forks source link

Tests fail with gcc 7.0.1 due to new aliasing warnings #148

Open tomhughes opened 7 years ago

tomhughes commented 7 years ago

Running make test with gcc 7.0.1 fails due to new aliasing warnings, promoted to errors by the -Werror switch in the makefile:

g++ -c -o out/binary_visitor_1.o test/t/binary_visitor_1.cpp -Iinclude -isystem test/include -std=c++11 -Werror -Wall -Wextra -pedantic -Wformat=2 -Wsign-conversion -Wshadow -Wunused-parameter -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -fvisibility=hidden -I/usr/include/catch -pthread
In file included from test/t/binary_visitor_1.cpp:2:0:
include/mapbox/variant.hpp: In instantiation of ‘T& mapbox::util::variant<Types>::get() [with T = int; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
test/t/binary_visitor_impl.hpp:180:9:   required from here
include/mapbox/variant.hpp:724:20: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
             return *reinterpret_cast<T*>(&data);
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/mapbox/variant.hpp: In instantiation of ‘T& mapbox::util::variant<Types>::get() [with T = double; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
test/t/binary_visitor_impl.hpp:187:9:   required from here
include/mapbox/variant.hpp:724:20: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
include/mapbox/variant.hpp: In instantiation of ‘const T& mapbox::util::variant<Types>::get_unchecked() const [with T = int; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
include/mapbox/variant.hpp:472:51:   required from ‘static R mapbox::util::detail::binary_dispatcher<F, V, R, T, Types ...>::apply_const(const V&, const V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T = int; Types = {double}]’
include/mapbox/variant.hpp:893:73:   required from ‘static decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply_const(v0, v1, forward<F>(f))) mapbox::util::variant<Types>::binary_visit(const V&, const V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; Types = {int, double}; decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply_const(v0, v1, forward<F>(f))) = double]’
include/mapbox/variant.hpp:987:27:   required from ‘decltype (V:: binary_visit(v0, v1, forward<F>(f))) mapbox::util::apply_visitor(F&&, const V&, const V&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; decltype (V:: binary_visit(v0, v1, forward<F>(f))) = double]’
test/t/binary_visitor_impl.hpp:28:5:   required from here
include/mapbox/variant.hpp:737:16: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
         return *reinterpret_cast<T const*>(&data);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/mapbox/variant.hpp: In instantiation of ‘T& mapbox::util::variant<Types>::get_unchecked() [with T = int; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
include/mapbox/variant.hpp:493:45:   required from ‘static R mapbox::util::detail::binary_dispatcher<F, V, R, T, Types ...>::apply(V&, V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T = int; Types = {double}]’
include/mapbox/variant.hpp:900:67:   required from ‘static decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply(v0, v1, forward<F>(f))) mapbox::util::variant<Types>::binary_visit(V&, V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; Types = {int, double}; decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply(v0, v1, forward<F>(f))) = double]’
include/mapbox/variant.hpp:994:27:   required from ‘decltype (V:: binary_visit(v0, v1, forward<F>(f))) mapbox::util::apply_visitor(F&&, V&, V&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; decltype (V:: binary_visit(v0, v1, forward<F>(f))) = double]’
test/t/binary_visitor_impl.hpp:68:5:   required from here
include/mapbox/variant.hpp:713:16: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
         return *reinterpret_cast<T*>(&data);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/mapbox/variant.hpp: In instantiation of ‘const T& mapbox::util::variant<Types>::get_unchecked() const [with T = double; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
include/mapbox/variant.hpp:401:44:   required from ‘static R mapbox::util::detail::binary_dispatcher_rhs<F, V, R, T0, T1>::apply_const(const V&, const V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T0 = int; T1 = double]’
include/mapbox/variant.hpp:477:80:   required from ‘static R mapbox::util::detail::binary_dispatcher<F, V, R, T, Types ...>::apply_const(const V&, const V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T = int; Types = {double}]’
include/mapbox/variant.hpp:893:73:   required from ‘static decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply_const(v0, v1, forward<F>(f))) mapbox::util::variant<Types>::binary_visit(const V&, const V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; Types = {int, double}; decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply_const(v0, v1, forward<F>(f))) = double]’
include/mapbox/variant.hpp:987:27:   required from ‘decltype (V:: binary_visit(v0, v1, forward<F>(f))) mapbox::util::apply_visitor(F&&, const V&, const V&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; decltype (V:: binary_visit(v0, v1, forward<F>(f))) = double]’
test/t/binary_visitor_impl.hpp:28:5:   required from here
include/mapbox/variant.hpp:737:16: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
         return *reinterpret_cast<T const*>(&data);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/mapbox/variant.hpp: In instantiation of ‘T& mapbox::util::variant<Types>::get_unchecked() [with T = double; typename std::enable_if<(mapbox::util::detail::direct_type<T, Types ...>::index != mapbox::util::detail::invalid_value)>::type* <anonymous> = 0; Types = {int, double}]’:
include/mapbox/variant.hpp:407:38:   required from ‘static R mapbox::util::detail::binary_dispatcher_rhs<F, V, R, T0, T1>::apply(V&, V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T0 = int; T1 = double]’
include/mapbox/variant.hpp:498:74:   required from ‘static R mapbox::util::detail::binary_dispatcher<F, V, R, T, Types ...>::apply(V&, V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; T = int; Types = {double}]’
include/mapbox/variant.hpp:900:67:   required from ‘static decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply(v0, v1, forward<F>(f))) mapbox::util::variant<Types>::binary_visit(V&, V&, F&&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; R = double; Types = {int, double}; decltype (mapbox::util::detail::binary_dispatcher<F, V, R, Types ...>::apply(v0, v1, forward<F>(f))) = double]’
include/mapbox/variant.hpp:994:27:   required from ‘decltype (V:: binary_visit(v0, v1, forward<F>(f))) mapbox::util::apply_visitor(F&&, V&, V&) [with F = const add_visitor&; V = mapbox::util::variant<int, double>; decltype (V:: binary_visit(v0, v1, forward<F>(f))) = double]’
test/t/binary_visitor_impl.hpp:68:5:   required from here
include/mapbox/variant.hpp:713:16: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
         return *reinterpret_cast<T*>(&data);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make: *** [Makefile:100: out/binary_visitor_1.o] Error 1
kkaefer commented 7 years ago

std::variant gets away without casts because it uses at its core a recursively(!) templated union so that it can write a static accessor that recursively goes through the nested union to access the correct data member by index. Since it uses union, it doesn't need to cast and can rely on the compiler to perform the correct alignment.

artemp commented 7 years ago

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80593

tomhughes commented 7 years ago

Oops. So that's a regression that came from a fix for an ARM code generation bug I reported with mapnik ;-)

See https://bugzilla.redhat.com/show_bug.cgi?id=1422456 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671 for the somewhat horrifying/incomprehensible history of the original bug...

artemp commented 7 years ago

@tomhughes 👍

daniel-j-h commented 7 years ago

Upstream fix landed and GCC 7.2 just got released: https://gcc.gnu.org/ml/gcc/2017-08/msg00129.html

Alan-Penkar commented 7 years ago

I was also having this issue with GCC 7.2. I tried to downgrade to gcc6 (using upgrade-alternatives) and I'm somehow still getting this error. Should gcc 6.4 be able to compile this? If not, what version of gcc do I need?