On 7/12/23 11:54, Patrick Palka wrote:
On Wed, 12 Jul 2023, Patrick Palka wrote:
We're not checking constraints of pointer/reference-to-function conversion
functions during overload resolution, which causes us to ICE on the first
testcase and incorrectly reject the second testcase.
Er, I noticed [over.call.object] doesn't exactly say that surrogate
call functions inherit the constraints of the corresponding conversion
function, but I reckon that's the intent?
I also assume so. OK.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/13?
PR c++/110535
gcc/cp/ChangeLog:
* call.cc (add_conv_candidate): Check constraints.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-surrogate1.C: New test.
* g++.dg/cpp2a/concepts-surrogate2.C: New test.
---
gcc/cp/call.cc | 8 ++++++++
gcc/testsuite/g++.dg/cpp2a/concepts-surrogate1.C | 12 ++++++++++++
gcc/testsuite/g++.dg/cpp2a/concepts-surrogate2.C | 14 ++++++++++++++
3 files changed, 34 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-surrogate1.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-surrogate2.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 15a3d6f2a1f..81935b83908 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2588,6 +2588,14 @@ add_conv_candidate (struct z_candidate **candidates,
tree fn, tree obj,
if (*candidates && (*candidates)->fn == totype)
return NULL;
+ if (!constraints_satisfied_p (fn))
+ {
+ reason = constraint_failure ();
+ viable = 0;
+ return add_candidate (candidates, fn, obj, arglist, len, convs,
+ access_path, conversion_path, viable, reason,
flags);
+ }
+
for (i = 0; i < len; ++i)
{
tree arg, argtype, convert_type = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate1.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate1.C
new file mode 100644
index 00000000000..e8481a31656
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate1.C
@@ -0,0 +1,12 @@
+// PR c++/110535
+// { dg-do compile { target c++20 } }
+
+using F = int(int);
+
+template<bool B>
+struct A {
+ operator F*() requires B;
+};
+
+int i = A<true>{}(0); // OK
+int j = A<false>{}(0); // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate2.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate2.C
new file mode 100644
index 00000000000..8bf8364beb7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-surrogate2.C
@@ -0,0 +1,14 @@
+// PR c++/110535
+// { dg-do compile { target c++20 } }
+
+using F = int(int);
+using G = long(int);
+
+template<bool B>
+struct A {
+ operator F&() requires B;
+ operator G&() requires (!B);
+};
+
+int i = A<true>{}(0); // { dg-bogus "ambiguous" }
+int j = A<false>{}(0); // { dg-bogus "ambiguous" }
--
2.41.0.327.gaa9166bcc0