* [PATCH] c++: ambiguous call not diagnosed after DR2352 [PR97296]
@ 2022-04-12 22:50 Marek Polacek
2022-04-13 2:47 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Marek Polacek @ 2022-04-12 22:50 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
DR 2352 changed the definitions of reference-related (so that it uses
"similar type" instead of "same type") and of reference-compatible (use
a standard conversion sequence). That means that reference-related is
now more broad, which means that we will be binding more things directly.
The original patch for DR 2352 caused some problems, which were fixed in
r276251 by creating a "fake" ck_qual in direct_reference_binding, so
that in
void f(int *); // #1
void f(const int * const &); // #2
int *x;
int main()
{
f(x); // call #1
}
we call #1. The extra ck_qual in #2 causes compare_ics to select #1,
which is a better match for "int *" because then we don't have to do
a qualification conversion.
Let's turn to the problem in this PR. We have
void f(const int * const &); // #1
void f(const int *); // #2
int *x;
int main()
{
f(x);
}
We arrive in compare_ics to decide which one is better. The ICS for #1
looks like
ck_ref_bind <- ck_qual <- ck_identity
const int *const & const int *const int *
and the ICS for #2 is
ck_qual <- ck_rvalue <- ck_identity
const int * int * int *
We strip the reference and then comp_cv_qual_signature when comparing two
ck_quals sees that "const int *" is a proper subset of "const int *const"
and we return -1. But that's wrong; presumably the top-level "const"
should be ignored and the call should be ambiguous. This patch adjust
the type of the "fake" ck_qual so that this problem doesn't arise.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
PR c++/97296
gcc/cp/ChangeLog:
* call.cc (direct_reference_binding): strip_top_quals when creating
a ck_qual.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/ref-bind4.C: Add dg-error.
* g++.dg/cpp0x/ref-bind8.C: New test.
---
gcc/cp/call.cc | 15 +++++++++++++--
gcc/testsuite/g++.dg/cpp0x/ref-bind4.C | 2 +-
gcc/testsuite/g++.dg/cpp0x/ref-bind8.C | 10 ++++++++++
3 files changed, 24 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 3a8d7e4b131..fc2fc009f14 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -1680,8 +1680,19 @@ direct_reference_binding (tree type, conversion *conv)
because the types "int *" and "const int *const" are
reference-related and we were binding both directly and they
had the same rank. To break it up, we add a ck_qual under the
- ck_ref_bind so that conversion sequence ranking chooses #1. */
- conv = build_conv (ck_qual, t, conv);
+ ck_ref_bind so that conversion sequence ranking chooses #1.
+
+ We strip_top_quals here which is also what standard_conversion
+ does. Failure to do so would confuse comp_cv_qual_signature
+ into thinking that in
+
+ void f(const int * const &); // #1
+ void f(const int *); // #2
+ int *x;
+ f(x);
+
+ #2 is a better match than #1 even thought they're ambiguous (97296). */
+ conv = build_conv (ck_qual, strip_top_quals (t), conv);
return build_conv (ck_ref_bind, type, conv);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
index 85ac9fbfd79..d296d7c3b72 100644
--- a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
@@ -51,6 +51,6 @@ g (int *p, const int *pc, const int **q)
similar types T1 and T2 (_conv.qual_), respectively, and the cv-
qualification signature of type T1 is a proper subset of the cv-
qualification signature of type T2 */
- f8 (q);
+ f8 (q); // { dg-error "call of overloaded" }
f9 (q);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
new file mode 100644
index 00000000000..eee78fd5e74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
@@ -0,0 +1,10 @@
+// PR c++/97296
+// { dg-do compile }
+
+void f(const int * const &);
+void f(const int *);
+int *x;
+int main()
+{
+ f(x); // { dg-error "call of overloaded" }
+}
base-commit: 3c742621ed28540cf42d4cfbc2bf03433cd26738
--
2.35.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] c++: ambiguous call not diagnosed after DR2352 [PR97296]
2022-04-12 22:50 [PATCH] c++: ambiguous call not diagnosed after DR2352 [PR97296] Marek Polacek
@ 2022-04-13 2:47 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2022-04-13 2:47 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 4/12/22 18:50, Marek Polacek wrote:
> DR 2352 changed the definitions of reference-related (so that it uses
> "similar type" instead of "same type") and of reference-compatible (use
> a standard conversion sequence). That means that reference-related is
> now more broad, which means that we will be binding more things directly.
>
> The original patch for DR 2352 caused some problems, which were fixed in
> r276251 by creating a "fake" ck_qual in direct_reference_binding, so
> that in
>
> void f(int *); // #1
> void f(const int * const &); // #2
> int *x;
> int main()
> {
> f(x); // call #1
> }
>
> we call #1. The extra ck_qual in #2 causes compare_ics to select #1,
> which is a better match for "int *" because then we don't have to do
> a qualification conversion.
>
> Let's turn to the problem in this PR. We have
>
> void f(const int * const &); // #1
> void f(const int *); // #2
> int *x;
> int main()
> {
> f(x);
> }
>
> We arrive in compare_ics to decide which one is better. The ICS for #1
> looks like
>
> ck_ref_bind <- ck_qual <- ck_identity
> const int *const & const int *const int *
>
> and the ICS for #2 is
>
> ck_qual <- ck_rvalue <- ck_identity
> const int * int * int *
>
> We strip the reference and then comp_cv_qual_signature when comparing two
> ck_quals sees that "const int *" is a proper subset of "const int *const"
> and we return -1. But that's wrong; presumably the top-level "const"
> should be ignored and the call should be ambiguous. This patch adjust
> the type of the "fake" ck_qual so that this problem doesn't arise.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
OK, thanks.
> PR c++/97296
>
> gcc/cp/ChangeLog:
>
> * call.cc (direct_reference_binding): strip_top_quals when creating
> a ck_qual.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/ref-bind4.C: Add dg-error.
> * g++.dg/cpp0x/ref-bind8.C: New test.
> ---
> gcc/cp/call.cc | 15 +++++++++++++--
> gcc/testsuite/g++.dg/cpp0x/ref-bind4.C | 2 +-
> gcc/testsuite/g++.dg/cpp0x/ref-bind8.C | 10 ++++++++++
> 3 files changed, 24 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
>
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 3a8d7e4b131..fc2fc009f14 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -1680,8 +1680,19 @@ direct_reference_binding (tree type, conversion *conv)
> because the types "int *" and "const int *const" are
> reference-related and we were binding both directly and they
> had the same rank. To break it up, we add a ck_qual under the
> - ck_ref_bind so that conversion sequence ranking chooses #1. */
> - conv = build_conv (ck_qual, t, conv);
> + ck_ref_bind so that conversion sequence ranking chooses #1.
> +
> + We strip_top_quals here which is also what standard_conversion
> + does. Failure to do so would confuse comp_cv_qual_signature
> + into thinking that in
> +
> + void f(const int * const &); // #1
> + void f(const int *); // #2
> + int *x;
> + f(x);
> +
> + #2 is a better match than #1 even thought they're ambiguous (97296). */
> + conv = build_conv (ck_qual, strip_top_quals (t), conv);
>
> return build_conv (ck_ref_bind, type, conv);
> }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
> index 85ac9fbfd79..d296d7c3b72 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
> @@ -51,6 +51,6 @@ g (int *p, const int *pc, const int **q)
> similar types T1 and T2 (_conv.qual_), respectively, and the cv-
> qualification signature of type T1 is a proper subset of the cv-
> qualification signature of type T2 */
> - f8 (q);
> + f8 (q); // { dg-error "call of overloaded" }
> f9 (q);
> }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
> new file mode 100644
> index 00000000000..eee78fd5e74
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind8.C
> @@ -0,0 +1,10 @@
> +// PR c++/97296
> +// { dg-do compile }
> +
> +void f(const int * const &);
> +void f(const int *);
> +int *x;
> +int main()
> +{
> + f(x); // { dg-error "call of overloaded" }
> +}
>
> base-commit: 3c742621ed28540cf42d4cfbc2bf03433cd26738
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-04-13 2:47 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-12 22:50 [PATCH] c++: ambiguous call not diagnosed after DR2352 [PR97296] Marek Polacek
2022-04-13 2:47 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).