Message ID | 20230712154138.2837658-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: constrained surrogate calls [PR110535] | expand |
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? > > 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 > >
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 >> >> >
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" }