mapbox/variant

Tests fail with gcc 7.0.1 due to new aliasing warnings

Opened this issue · 6 comments

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

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.

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...

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

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?