Created attachment 46315 [details] Minimal example Since upgrading to GCC 9.1.1, I am getting the following errors when running clang-tidy (8.0.0) on this minimal example. Not sure whether this is a bug in the libstdc++ headers or in clang, but it seems to be related to the noexcept specifier on __get(). The code compiles fine with g++. #include <variant> int main() { std::variant<int, double> v; v = 5; int i = std::get<int>(v); return 0; } In order to reproduce from the zipped folder: mkdir build && cd build cmake .. make clang-tidy ../example.cpp give the following errors for me. [build]$ clang-tidy ../example.cpp 6 errors generated. Error while processing /home/fedora/example/build/../example.cpp. /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:266:10: error: cannot cast 'const std::variant<int, double>' to its private base class 'std::__detail::__variant::_Variant_storage<true, int, double>' [clang-diagnostic-error] std::forward<_Variant>(__v)._M_u); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1610:35: note: in instantiation of function template specialization 'std::__detail::__variant::__get<0, const std::variant<int, double> &>' requested here return __detail::__variant::__get<_Np>(__v); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1359:11: note: in instantiation of function template specialization 'std::get<0, int, double>' requested here std::get<__index>(*this) = std::forward<_Tp>(__rhs); ^ /home/fedora/example/example.cpp:5:5: note: in instantiation of function template specialization 'std::variant<int, double>::operator=<int>' requested here v = 5; ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1220:7: note: constrained by private inheritance here : private __detail::__variant::_Variant_base<_Types...>, ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:266:10: error: cannot cast 'std::variant<int, double>' to its private base class 'std::__detail::__variant::_Variant_storage<true, int, double>' [clang-diagnostic-error] std::forward<_Variant>(__v)._M_u); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1588:35: note: in instantiation of function template specialization 'std::__detail::__variant::__get<0, std::variant<int, double> &>' requested here return __detail::__variant::__get<_Np>(__v); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1061:19: note: in instantiation of function template specialization 'std::get<0, int, double>' requested here return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); ^ /home/fedora/example/example.cpp:7:16: note: in instantiation of function template specialization 'std::get<int, int, double>' requested here int i = std::get<int>(v); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1220:7: note: constrained by private inheritance here : private __detail::__variant::_Variant_base<_Types...>, ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:266:38: error: '_M_u' is a private member of 'std::__detail::__variant::_Variant_storage<true, int, double>' [clang-diagnostic-error] std::forward<_Variant>(__v)._M_u); ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1220:7: note: constrained by private inheritance here : private __detail::__variant::_Variant_base<_Types...>, ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:453:34: note: member is declared here _Variadic_union<_Types...> _M_u; ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1359:31: error: cannot assign to return value because function 'get<0, int, double>' returns a const value [clang-diagnostic-error] std::get<__index>(*this) = std::forward<_Tp>(__rhs); ^ /home/fedora/example/example.cpp:5:5: note: in instantiation of function template specialization 'std::variant<int, double>::operator=<int>' requested here v = 5; ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:134:15: note: function 'get<0, int, double>' which returns const-qualified type 'const variant_alternative_t<0UL, variant<int, double> > &' (aka 'const int &') declared here constexpr variant_alternative_t<_Np, variant<_Types...>> const& ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:1559:55: error: '__get' is missing exception specification 'noexcept' [clang-diagnostic-error] friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v); ^ /home/fedora/example/example.cpp:4:29: note: in instantiation of template class 'std::variant<int, double>' requested here std::variant<int, double> v; ^ /usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/variant:263:5: note: previous declaration is here __get(_Variant&& __v) noexcept ^ Found compiler error(s).
I was able to rectify the issue by removing the noexcept in <variant> on line 263. I assume, that would imply that the noexcept's on the other overloads would also need to be removed.
No, it should be added to the friend declaration. I missed the friend declaration when I added 'noexcept' elsewhere in r270501.
Yep! I added the noexcept on there on my local version and that also resolved the issue.
Author: redi Date: Fri May 10 21:41:19 2019 New Revision: 271079 URL: https://gcc.gnu.org/viewcvs?rev=271079&root=gcc&view=rev Log: PR libstdc++/90397 fix std::variant friend declarations Clang diagnoses the inconsistent noexcept-specifier on the friend declaration of __get. Add it, and also on __get_storage. PR libstdc++/90397 * include/std/variant (_Variant_storage<false, Types...>::_M_storage()) (_Variant_storage<true, Types...>::_M_reset())) (_Variant_storage<true, Types...>::_M_storage())): Add noexcept. (__get_storage): Likewise. (variant): Add noexcept to friend declarations for __get and __get_storage. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/variant
Author: redi Date: Fri May 10 22:23:10 2019 New Revision: 271083 URL: https://gcc.gnu.org/viewcvs?rev=271083&root=gcc&view=rev Log: PR libstdc++/90397 fix std::variant friend declaration Clang diagnoses insert inconsistent noexcept-specifier on the friend declaration of __get. Add . PR libstdc++/90397 * include/std/variant (variant): Add noexcept to friend declaration. Modified: branches/gcc-9-branch/libstdc++-v3/ChangeLog branches/gcc-9-branch/libstdc++-v3/include/std/variant
fixed on trunk and gcc-9-branch
But, what about bug in gcc by itself, because of it doesn't report compile error, is it reported as one more bug?
G++ allowed it because the mismatch was in a system header. If you use -Wsystem-headers then GCC 9.1 gives a warning about it: /xhome/jwakely/gcc/9.1.0/include/c++/9.1.0/variant: In instantiation of 'class std::variant<A, B>': var.cc:14:44: required from here /xhome/jwakely/gcc/9.1.0/include/c++/9.1.0/variant:1559:34: warning: declaration of 'template<long unsigned int _Np, class _Vp> constexpr decltype(auto) std::__detail::__variant::__get(_Vp&&)' has a different exception specifier [-Wsystem-headers] 1559 | friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v); | ^~~~~~~~ /xhome/jwakely/gcc/9.1.0/include/c++/9.1.0/variant:263:5: note: from previous declaration 'template<long unsigned int _Np, class _Variant> constexpr decltype(auto) std::__detail::__variant::__get(_Variant&&) noexcept' 263 | __get(_Variant&& __v) noexcept | ^~~~~ If you use -pedantic-errors then you get an error.