From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id A38CE3958C37 for ; Tue, 4 May 2021 11:20:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A38CE3958C37 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-212-EwBNM8oGNEyUIbTizIaBmA-1; Tue, 04 May 2021 07:20:00 -0400 X-MC-Unique: EwBNM8oGNEyUIbTizIaBmA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 970461898296; Tue, 4 May 2021 11:19:59 +0000 (UTC) Received: from localhost (unknown [10.33.36.164]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F7E05C559; Tue, 4 May 2021 11:19:59 +0000 (UTC) Date: Tue, 4 May 2021 12:19:58 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Do not use deduced return type for std::visit [PR 100384] Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="/jCBHp/J2zi5Pxo8" Content-Disposition: inline X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, URI_HEX autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 May 2021 11:20:07 -0000 --/jCBHp/J2zi5Pxo8 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline This avoids errors outside the immediate context when std::visit is an overload candidate because of ADL, but not actually viable. The solution is to give std::visit a non-deduced return type. New helpers are introduced for that, and existing ones refactored slightly. libstdc++-v3/ChangeLog: PR libstdc++/100384 * include/std/variant (__get_t): New alias template yielding the return type of std::get on a variant. (__visit_result_t): New alias template yielding the result of std::visit. (__same_types): Move into namespace __detail::__variant. (__check_visitor_results): Likewise. Use __invoke_result_t and __get_t. (__check_visitor_result): Remove. (visit): Use __visit_result_t for return type. * testsuite/20_util/variant/100384.cc: New test. Tested powerpc64le-linux. Committed to trunk. This should be backported too, as the std::visit on the branches has this bug. --/jCBHp/J2zi5Pxo8 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" commit af5b2b911dd80ae9cc87404b7e7ab807cf6655d4 Author: Jonathan Wakely Date: Tue May 4 12:16:46 2021 libstdc++: Do not use deduced return type for std::visit [PR 100384] This avoids errors outside the immediate context when std::visit is an overload candidate because of ADL, but not actually viable. The solution is to give std::visit a non-deduced return type. New helpers are introduced for that, and existing ones refactored slightly. libstdc++-v3/ChangeLog: PR libstdc++/100384 * include/std/variant (__get_t): New alias template yielding the return type of std::get on a variant. (__visit_result_t): New alias template yielding the result of std::visit. (__same_types): Move into namespace __detail::__variant. (__check_visitor_results): Likewise. Use __invoke_result_t and __get_t. (__check_visitor_result): Remove. (visit): Use __visit_result_t for return type. * testsuite/20_util/variant/100384.cc: New test. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 1ef9b9725e2..9b2bc440841 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1063,6 +1063,25 @@ namespace __variant std::index_sequence<__indices...>> : _Base_dedup<__indices, __poison_hash>>... { }; + template + using __get_t = decltype(std::get<_Np>(std::declval<_Variant>())); + + // Return type of std::visit. + template + using __visit_result_t + = invoke_result_t<_Visitor, __get_t<0, _Variants>...>; + + template + constexpr inline bool __same_types = (is_same_v<_Tp, _Types> && ...); + + template + constexpr bool __check_visitor_results(std::index_sequence<_Idxs...>) + { + return __same_types< + invoke_result_t<_Visitor, __get_t<_Idxs, _Variant>>... + >; + } + } // namespace __variant } // namespace __detail @@ -1248,7 +1267,8 @@ namespace __variant #endif template - constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); + constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> + visit(_Visitor&&, _Variants&&...); template inline enable_if_t<(is_move_constructible_v<_Types> && ...) @@ -1715,41 +1735,21 @@ namespace __variant std::forward<_Variants>(__variants)...); } - template - constexpr inline bool __same_types = (is_same_v<_Tp, _Types> && ...); - - template - decltype(auto) - __check_visitor_result(_Visitor&& __vis, _Variant&& __variant) - { - return std::__invoke(std::forward<_Visitor>(__vis), - std::get<_Idx>(std::forward<_Variant>(__variant))); - } - - template - constexpr bool __check_visitor_results(std::index_sequence<_Idxs...>) - { - return __same_types( - std::declval<_Visitor>(), - std::declval<_Variant>()))...>; - } - - template - constexpr decltype(auto) + constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> visit(_Visitor&& __visitor, _Variants&&... __variants) { if ((__variants.valueless_by_exception() || ...)) __throw_bad_variant_access("std::visit: variant is valueless"); - using _Result_type = std::invoke_result_t<_Visitor, - decltype(std::get<0>(std::declval<_Variants>()))...>; + using _Result_type + = __detail::__variant::__visit_result_t<_Visitor, _Variants...>; using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>; if constexpr (sizeof...(_Variants) == 1) { - constexpr bool __visit_rettypes_match = + constexpr bool __visit_rettypes_match = __detail::__variant:: __check_visitor_results<_Visitor, _Variants...>( std::make_index_sequence< std::variant_size...>::value>()); diff --git a/libstdc++-v3/testsuite/20_util/variant/100384.cc b/libstdc++-v3/testsuite/20_util/variant/100384.cc new file mode 100644 index 00000000000..4866aa017ff --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/100384.cc @@ -0,0 +1,9 @@ +// { dg-do compile { target c++17 } } + +#include + +int visit(int*, std::true_type) { return 0; } + +const std::true_type dat; + +int i = visit(nullptr, dat); --/jCBHp/J2zi5Pxo8--