Skip to content

Commit 85ae54e

Browse files
committed
c++: ambiguous call not diagnosed after DR2352 [PR97296]
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. 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.
1 parent 9645279 commit 85ae54e

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

gcc/cp/call.cc

+13-2
Original file line numberDiff line numberDiff line change
@@ -1680,8 +1680,19 @@ direct_reference_binding (tree type, conversion *conv)
16801680
because the types "int *" and "const int *const" are
16811681
reference-related and we were binding both directly and they
16821682
had the same rank. To break it up, we add a ck_qual under the
1683-
ck_ref_bind so that conversion sequence ranking chooses #1. */
1684-
conv = build_conv (ck_qual, t, conv);
1683+
ck_ref_bind so that conversion sequence ranking chooses #1.
1684+
1685+
We strip_top_quals here which is also what standard_conversion
1686+
does. Failure to do so would confuse comp_cv_qual_signature
1687+
into thinking that in
1688+
1689+
void f(const int * const &); // #1
1690+
void f(const int *); // #2
1691+
int *x;
1692+
f(x);
1693+
1694+
#2 is a better match than #1 even though they're ambiguous (97296). */
1695+
conv = build_conv (ck_qual, strip_top_quals (t), conv);
16851696

16861697
return build_conv (ck_ref_bind, type, conv);
16871698
}

gcc/testsuite/g++.dg/cpp0x/ref-bind4.C

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ g (int *p, const int *pc, const int **q)
5151
similar types T1 and T2 (_conv.qual_), respectively, and the cv-
5252
qualification signature of type T1 is a proper subset of the cv-
5353
qualification signature of type T2 */
54-
f8 (q);
54+
f8 (q); // { dg-error "call of overloaded" }
5555
f9 (q);
5656
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// PR c++/97296
2+
// { dg-do compile }
3+
4+
void f(const int * const &);
5+
void f(const int *);
6+
int *x;
7+
int main()
8+
{
9+
f(x); // { dg-error "call of overloaded" }
10+
}

0 commit comments

Comments
 (0)