On 2/18/21 9:22 PM, Jason Merrill wrote:
When compiling this testcase, trying to resolve the initialization for the
tuple member ends up recursively considering the same set of tuple
constructor overloads, and since two of them separately depend on
is_constructible, the one we try second fails to instantiate
is_constructible because we're still in the middle of instantiating it the
first time.
Fixed by implementing an optimization that someone suggested we were already
doing: if we see a non-template candidate that is a perfect match for all
arguments, we can skip considering template candidates at all. It would be
enough to do this only when LOOKUP_DEFAULTED, but it shouldn't hurt in other
cases.
>From d909ead68214042e9876a8df136d0835273d4b86 Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Thu, 18 Feb 2021 21:27:37 -0500
Subject: [PATCH] c++: Tweak PR969626 patch
To: gcc-patches@gcc.gnu.org
It occurred to me that other types of conversions use rvaluedness_matches_p,
but those uses don't affect overload resolution, so we shouldn't look at the
flag for them. Fixing that made decltype64.C compile successfully, because
the non-template candidate was a perfect match, so we now wouldn't consider
the broken template. Changing the argument to const& makes it no longer a
perfect match (because of the added const), so we again get the infinite
recursion.
This illustrates the limited nature of this optimization/recursion break; it
works for most copy/move constructors because the constructor we're looking
for is almost always a perfect match. If it happens to help improve compile
time for other calls, that's just a bonus.
gcc/cp/ChangeLog:
PR c++/96926
* call.c (perfect_conversion_p): Limit rvalueness
test to reference bindings.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/decltype64.C: Change argument to const&.
---
gcc/cp/call.c | 14 ++++++++------
gcc/testsuite/g++.dg/cpp0x/decltype64.C | 2 +-
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bc369c68c5a..0ba0e19ae08 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5864,12 +5864,14 @@ perfect_conversion_p (conversion *conv)
{
if (CONVERSION_RANK (conv) != cr_identity)
return false;
- if (!conv->rvaluedness_matches_p)
- return false;
- if (conv->kind == ck_ref_bind
- && !same_type_p (TREE_TYPE (conv->type),
- next_conversion (conv)->type))
- return false;
+ if (conv->kind == ck_ref_bind)
+ {
+ if (!conv->rvaluedness_matches_p)
+ return false;
+ if (!same_type_p (TREE_TYPE (conv->type),
+ next_conversion (conv)->type))
+ return false;
+ }
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype64.C b/gcc/testsuite/g++.dg/cpp0x/decltype64.C
index 46d18594c94..0cd614cceeb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype64.C
@@ -5,7 +5,7 @@ template<int I>
struct index
{};
-constexpr int recursive_impl(index<0u>)
+constexpr int recursive_impl(const index<0u>&)
{
return 0;
}
--
2.27.0