Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std::variant build error on CentOS7 and g++9.3 #30118

Closed
jiminj opened this issue Jun 27, 2022 · 2 comments
Closed

std::variant build error on CentOS7 and g++9.3 #30118

jiminj opened this issue Jun 27, 2022 · 2 comments

Comments

@jiminj
Copy link

jiminj commented Jun 27, 2022

What version of gRPC and what language are you using?

1.47.0. Confirmed that the same error occurs on 1.46.x

What operating system (Linux, Windows,...) and version?

CentOS 7.4, LIBC2.17

What runtime / compiler are you using (e.g. python version or version of gcc)

GCC-9.3.1 (by devtoolset-9)

What did you do?

I bumped up grpc version from 1.45.2 to 1.47.0 for my C++ 17 project and got some build errors related to std::variant (see below for the error message).

I guess this is a kind of compatibility issue related to the implementation of std::variant of CentOS's devtoolset-9 since the errors disappear when I let the project use Abseil version of variant implementation by not designating the project standard as C++17 (set(CMAKE_CXX_STANDARD 17)). I also have tested it for Ubuntu 18.04 with gcc 9.4 & gcc 7.5 and confirmed that those have been built without any issue. Under my investigation so far, the issue came from this line (L144).

static constexpr size_t kClusterIndex = 0;
static constexpr size_t kWeightedClustersIndex = 1;
static constexpr size_t kClusterSpecifierPluginIndex = 2;
absl::variant<std::string, std::vector<ClusterWeight>, std::string>
action;

Although std::varaint should be allowed to have the same type more than once, it seems that having duplicated types becomes somewhat problematic under certain circumstances. I found the below edit bypasses the build error which is just to confirm this.

static constexpr size_t kClusterIndex = 0;
static constexpr size_t kWeightedClustersIndex = 1;
static constexpr size_t kClusterSpecifierPluginIndex = 0;
absl::variant<std::string, std::vector<ClusterWeight>> action; // remove second std::string then it builds successful

Below is the command to repod on CentOS 7.4, you need to have CMake dist.

# install devtoolset-9
$ yum update -y
$ yum install -y centos-release-scl
$ yum install -y devtoolset-9
$ scl enable devtoolset-9 bash

$ git clone --recurse-submodules https://github.com/grpc/grpc.git && cd grpc
$ git checkout 2717aa8 && git submodule update --recursive    # Checkout to 1.47.0
$ mkdir build && cd build
$ cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_CXX_STANDARD=17 ..
$ make

Should be related to this issue #29984

What did you expect to see?

A successful compilation

What did you see instead?

You can see the full error log here

[ 27%] Building CXX object CMakeFiles/grpc.dir/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc.o
/opt/rh/devtoolset-9/root/usr/bin/c++ -DCARES_STATICLIB -I/root/grpc/third_party/re2 -I/root/grpc/third_party/zlib -I/root/grpc/include -I/root/grpc -I/root/grpc/third_party/address_sorting/include -I/root/grpc/build/third_party/re2 -I/root/grpc/third_party/boringssl-with-bazel/src/include -I/root/grpc/src/core/ext/upb-generated -I/root/grpc/src/core/ext/upbdefs-generated -I/root/grpc/third_party/upb -I/root/grpc/third_party/xxhash -I/root/grpc/build/third_party/zlib -I/root/grpc/build/third_party/cares/cares -I/root/grpc/third_party/cares/cares -I/root/grpc/third_party/cares/cares/include -I/root/grpc/third_party/abseil-cpp -fPIC -pthread -std=c++17 -MD -MT CMakeFiles/grpc.dir/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc.o -MF CMakeFiles/grpc.dir/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc.o.d -o CMakeFiles/grpc.dir/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc.o -c /root/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
In file included from /root/grpc/third_party/abseil-cpp/absl/types/variant.h:50,
                 from /root/grpc/third_party/abseil-cpp/absl/status/statusor.h:51,
                 from /root/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc:36:
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant: In instantiation of 'std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)> mutable [with auto:3 = const std::basic_string<char>&; auto:4 = std::integral_constant<long unsigned int, 0>]':
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/invoke.h:60:36:   required from 'constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = std::__detail::__variant::__variant_idx_cookie; _Fn = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)>; _Args = {const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::integral_constant<long unsigned int, 0>}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/invoke.h:95:40:   required from 'constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)>; _Args = {const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::integral_constant<long unsigned int, 0>}; typename std::__invoke_result<_Functor, _ArgTypes>::type = std::__detail::__variant::__variant_idx_cookie]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:961:24:   required from 'static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke_impl(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = std::__detail::__variant::__variant_idx_cookie; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)>&&; _Variants = {const std::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&}; long unsigned int ...__indices = {0}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:980:28:   required from 'static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__do_visit_invoke(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = std::__detail::__variant::__variant_idx_cookie; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)>&&; _Variants = {const std::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&}; long unsigned int ...__indices = {0}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:996:28:   required from 'static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = std::__detail::__variant::__variant_idx_cookie; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >}]::<lambda(auto:3&&, auto:4)>&&; _Variants = {const std::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&}; long unsigned int ...__indices = {0}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1005:28:   [ skipping 11 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1005:28:   required from 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with bool __same_return_types = true; _Result_type = std::__detail::__variant::__variant_idx_cookie; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]::<lambda(auto:3&&, auto:4)>&&; _Variants = {const std::variant<grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction>&}; long unsigned int ...__indices = {1}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:915:56:   required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&, _Tp*) [with bool __do_cookie = true; long unsigned int __index = 1; _Tp = std::__detail::__variant::_Multi_array<std::__detail::__variant::__variant_idx_cookie (*)(std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]::<lambda(auto:3&&, auto:4)>&&, const std::variant<grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction>&)>; bool __same_return_types = true; _Result_type = std::__detail::__variant::__variant_idx_cookie; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]::<lambda(auto:3&&, auto:4)>&&; long unsigned int ...__dimensions = {3}; _Variants = {const std::variant<grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction>&}; long unsigned int ...__indices = {}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:896:47:   required from 'constexpr const _Array_type std::__detail::__variant::__gen_vtable<true, std::__detail::__variant::__variant_idx_cookie, std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]::<lambda(auto:3&&, auto:4)>&&, const std::variant<grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction>&>::_S_vtable'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1638:23:   required from 'constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with bool __use_index = true; bool __same_return_types = true; _Visitor = std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]::<lambda(auto:3&&, auto:4)>; _Variants = {const std::variant<grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction>&}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:586:32:   required from 'std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>& std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>::operator=(const std::__detail::__variant::_Copy_assign_base<<anonymous>, _Types>&) [with bool <anonymous> = false; _Types = {grpc_core::XdsRouteConfigResource::Route::UnknownAction, grpc_core::XdsRouteConfigResource::Route::RouteAction, grpc_core::XdsRouteConfigResource::Route::NonForwardingAction}]'
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:636:12:   required from here
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:609:6: error: no matching function for call to 'std::variant<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight, std::allocator<grpc_core::XdsRouteConfigResource::Route::RouteAction::ClusterWeight> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::variant(const std::basic_string<char>&)'
  609 |    = variant<_Types...>(__rhs_mem);
      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1342:2: note: candidate: 'template<long unsigned int _Np, class _Up, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, std::initializer_list<_Up>, _Args&& ...)'
 1342 |  variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
      |  ^~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1342:2: note:   template argument deduction/substitution failed:
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:609:6: note:   'std::basic_string<char>' is not derived from 'std::in_place_index_t<_Idx>'
  609 |    = variant<_Types...>(__rhs_mem);
      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1331:2: note: candidate: 'template<long unsigned int _Np, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, _Args&& ...)'
 1331 |  variant(in_place_index_t<_Np>, _Args&&... __args)
      |  ^~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1331:2: note:   template argument deduction/substitution failed:
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:609:6: note:   'std::basic_string<char>' is not derived from 'std::in_place_index_t<_Idx>'
  609 |    = variant<_Types...>(__rhs_mem);
      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1321:2: note: candidate: 'template<class _Tp, class _Up, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, std::initializer_list<_Up>, _Args&& ...)'
 1321 |  variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
      |  ^~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1321:2: note:   template argument deduction/substitution failed:
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:609:6: note:   'std::basic_string<char>' is not derived from 'std::in_place_type_t<_Tp>'
  609 |    = variant<_Types...>(__rhs_mem);
      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1311:2: note: candidate: 'template<class _Tp, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, _Args&& ...)'
 1311 |  variant(in_place_type_t<_Tp>, _Args&&... __args)
      |  ^~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1311:2: note:   template argument deduction/substitution failed:
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:609:6: note:   'std::basic_string<char>' is not derived from 'std::in_place_type_t<_Tp>'
  609 |    = variant<_Types...>(__rhs_mem);
      |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1301:2: note: candidate: 'template<class _Tp, class, class, class _Tj, class> constexpr std::variant<_Types>::variant(_Tp&&)'
 1301 |  variant(_Tp&& __t)
      |  ^~~~~~~
/opt/rh/devtoolset-9/root/usr/include/c++/9/variant:1301:2: note:   template argument deduction/substitution failed:

Anything else we should know about your project / environment?

@jiminj
Copy link
Author

jiminj commented Jun 28, 2022

Dug a little deeper. Found the assigment operator issue of std::variant in GCC bugzilla. : Issues 91807 / github gcc mirror link

Apparently, this bug has been introduced at version 9, the fix was included to GCC 9.4.0, GCC 10.2.0 and GCC 11.1.0 releases. In other words, the compatibilities for certain gcc releases less than these versions are currently broken.

BTW, confirmed that defining a copy assignment operator overload for struct RouteAction could avoid the issue. Not looks really ideal though.

      RouteAction & operator=(const RouteAction & other) {
        hash_policies = other.hash_policies;
        retry_policy = other.retry_policy;
        switch(other.action.index()) {
          case kClusterIndex:
            action.emplace<kClusterIndex>(
                std::get<kClusterIndex>(other.action));
            break;
          case kWeightedClustersIndex:
            action.emplace<kWeightedClustersIndex>(
                std::get<kWeightedClustersIndex>(other.action));
            break;
          case kClusterSpecifierPluginIndex:
            action.emplace<kClusterSpecifierPluginIndex>(
                std::get<kClusterSpecifierPluginIndex>(other.action));
            break;
        }
        max_stream_duration = other.max_stream_duration;
        return *this;
      }

@veblush
Copy link
Contributor

veblush commented Jun 28, 2022

Thanks for reporting & investigating this issue. But I think we need to close it since it's a gcc bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants