aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-09-28 15:35:37 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-09-28 15:35:37 +0000
commit406c9a1173f79dc0fb3231edb51690c1dd73f6a0 (patch)
treec97288a968cae89f56b73fb3f74a970d5234bd01 /gcc
parent7cf66a2dbe8017f59d2b28e8db3de8067efcc43e (diff)
downloadgcc-406c9a1173f79dc0fb3231edb51690c1dd73f6a0.zip
gcc-406c9a1173f79dc0fb3231edb51690c1dd73f6a0.tar.gz
gcc-406c9a1173f79dc0fb3231edb51690c1dd73f6a0.tar.bz2
PR c++/91889 - follow-up fix for DR 2352.
* call.c (involves_qualification_conversion_p): New function. (direct_reference_binding): Build a ck_qual if the conversion would involve a qualification conversion. (convert_like_real): Strip the conversion created by the ck_qual in direct_reference_binding. * g++.dg/cpp0x/ref-bind3.C: Add dg-error. * g++.dg/cpp0x/ref-bind4.C: New test. * g++.dg/cpp0x/ref-bind5.C: New test. * g++.dg/cpp0x/ref-bind6.C: New test. * g++.old-deja/g++.pt/spec35.C: Revert earlier change. From-SVN: r276251
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c46
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-bind3.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-bind4.C56
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-bind5.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-bind6.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec35.C8
8 files changed, 159 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c30d704..a1e520a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2019-09-28 Marek Polacek <polacek@redhat.com>
+ PR c++/91889 - follow-up fix for DR 2352.
+ * call.c (involves_qualification_conversion_p): New function.
+ (direct_reference_binding): Build a ck_qual if the conversion
+ would involve a qualification conversion.
+ (convert_like_real): Strip the conversion created by the ck_qual
+ in direct_reference_binding.
+
PR c++/91921 - stray warning with -Woverloaded-virtual.
* class.c (warn_hidden): Only emit the second part of
-Woverloaded-virtual if the first part was issued. Use inform instead
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5ccf3b8..56dcbd3 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1555,6 +1555,27 @@ reference_compatible_p (tree t1, tree t2)
return true;
}
+/* Return true if converting FROM to TO would involve a qualification
+ conversion. */
+
+static bool
+involves_qualification_conversion_p (tree to, tree from)
+{
+ /* If we're not convering a pointer to another one, we won't get
+ a qualification conversion. */
+ if (!((TYPE_PTR_P (to) && TYPE_PTR_P (from))
+ || (TYPE_PTRDATAMEM_P (to) && TYPE_PTRDATAMEM_P (from))))
+ return false;
+
+ conversion *conv = standard_conversion (to, from, NULL_TREE,
+ /*c_cast_p=*/false, 0, tf_none);
+ for (conversion *t = conv; t; t = next_conversion (t))
+ if (t->kind == ck_qual)
+ return true;
+
+ return false;
+}
+
/* A reference of the indicated TYPE is being bound directly to the
expression represented by the implicit conversion sequence CONV.
Return a conversion sequence for this binding. */
@@ -1598,6 +1619,19 @@ direct_reference_binding (tree type, conversion *conv)
That way, convert_like knows not to generate a temporary. */
conv->need_temporary_p = false;
}
+ else if (involves_qualification_conversion_p (t, conv->type))
+ /* Represent the qualification conversion. After DR 2352
+ #1 and #2 were indistinguishable conversion sequences:
+
+ void f(int*); // #1
+ void f(const int* const &); // #2
+ void g(int* p) { f(p); }
+
+ 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);
return build_conv (ck_ref_bind, type, conv);
}
@@ -7342,6 +7376,18 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
tree ref_type = totype;
+ /* direct_reference_binding might have inserted a ck_qual under
+ this ck_ref_bind for the benefit of conversion sequence ranking.
+ Ignore the conversion; we'll create our own below. */
+ if (next_conversion (convs)->kind == ck_qual)
+ {
+ gcc_assert (same_type_p (TREE_TYPE (expr),
+ next_conversion (convs)->type));
+ /* Strip the cast created by the ck_qual; cp_build_addr_expr
+ below expects an lvalue. */
+ STRIP_NOPS (expr);
+ }
+
if (convs->bad_p && !next_conversion (convs)->bad_p)
{
tree extype = TREE_TYPE (expr);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 104a83b..ecdce9b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2019-09-28 Marek Polacek <polacek@redhat.com>
+ PR c++/91889 - follow-up fix for DR 2352.
+ * g++.dg/cpp0x/ref-bind3.C: Add dg-error.
+ * g++.dg/cpp0x/ref-bind4.C: New test.
+ * g++.dg/cpp0x/ref-bind5.C: New test.
+ * g++.dg/cpp0x/ref-bind6.C: New test.
+ * g++.old-deja/g++.pt/spec35.C: Revert earlier change.
+
PR c++/91921 - stray warning with -Woverloaded-virtual.
* g++.dg/warn/Woverloaded-2.C: New.
* g++.dg/warn/Woverloaded-2.h: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind3.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind3.C
index 16e1bfe..b2c85ec 100644
--- a/gcc/testsuite/g++.dg/cpp0x/ref-bind3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind3.C
@@ -1,22 +1,18 @@
// PR c++/91844 - Implement CWG 2352, Similar types and reference binding.
// { dg-do compile { target c++11 } }
-template<typename T> int f (const T *const &); // (1)
-template<typename T> int f (T *const &); // (2)
-template<typename T> int f (T *); // (3)
-
-/* Before CWG 2352, (2) was a better match than (1), but (2) and (3) were
- equally good, so there was an ambiguity. (2) was better than (1) because
- (1) required a qualification conversion whereas (2) didn't. But with this
- CWG, (1) no longer requires a qualification conversion, because the types
- "const int* const" and "int *" are now considered reference-related and we
- bind directly, and (1) is more specialized than (2). And (1) is also a
- better match than (3). */
+template<typename T> int f (const T *const &); // 1
+template<typename T> int f (T *const &); // 2
+template<typename T> int f (T *); // 3
+/* There's an ambiguity: (2) is a better match than (1) because
+ (1) requires a qualification conversion whereas (2) doesn't, but
+ (2) and (3) are indistinguishable conversion sequences. */
+
void
g (int *p, const int *q, const int *const r)
{
- f (p); // calls (1)
- f (q); // calls (1)
- f (r); // calls (1)
+ f (p); // { dg-error "call of overloaded" }
+ f (q);
+ f (r);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
new file mode 100644
index 0000000..85ac9fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind4.C
@@ -0,0 +1,56 @@
+// PR c++/91889 - follow-up fix for DR 2352.
+// { dg-do compile { target c++11 } }
+
+int i;
+
+void f1 (int *);
+void f1 (const int *const &);
+
+void f2 (int *);
+void f2 (const int *&);
+
+void f3 (const int *);
+void f3 (int *const &);
+
+void f4 (int *&);
+void f4 (int *const &);
+
+void f5 (const int *&);
+void f5 (int *const &);
+
+void f6 (int *const &);
+void f6 (const int *const &);
+
+void f7 (int **const);
+void f7 (const int *const *const &);
+
+void f8 (const int *const *);
+void f8 (const int *const *const &);
+
+void f9 (int *const *);
+void f9 (const int *const *const &);
+
+void
+g (int *p, const int *pc, const int **q)
+{
+ f1 (p);
+ f1 (pc);
+ f2 (p);
+ f2 (pc);
+ f3 (p);
+ f3 (pc);
+ f4 (p);
+ f5 (p);
+ f5 (pc);
+ f6 (p);
+ f6 (pc);
+ f7 (q);
+ /* [over.ics.rank]
+
+ --S1 and S2 differ only in their qualification conversion and yield
+ 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);
+ f9 (q);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind5.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind5.C
new file mode 100644
index 0000000..d528b87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind5.C
@@ -0,0 +1,17 @@
+// PR c++/91889 - follow-up fix for DR 2352.
+// { dg-do compile { target c++11 } }
+
+template <typename U> struct A { typedef U *type; };
+struct B {
+ typedef A<B>::type node_ptr;
+};
+struct C {
+ typedef B::node_ptr node_ptr;
+ typedef A<const B>::type const_node_ptr;
+};
+struct {
+ void to_value_ptr(C::node_ptr) {};
+ void to_value_ptr(const C::const_node_ptr &);
+} b;
+C::node_ptr a;
+void fn1() { b.to_value_ptr(a); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-bind6.C b/gcc/testsuite/g++.dg/cpp0x/ref-bind6.C
new file mode 100644
index 0000000..c85a5cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-bind6.C
@@ -0,0 +1,12 @@
+// PR c++/91889 - follow-up fix for DR 2352.
+// { dg-do compile { target c++11 } }
+
+template <typename T> struct A {
+ A(const T &);
+};
+
+struct {
+ int *m;
+} a;
+
+void fn1() { A<const int *>(a.m); }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec35.C b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
index 93e953d..1debf91 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
@@ -14,9 +14,9 @@ template <typename T> int Foo (T &); // { dg-message "note" } candidate
template <typename T> int Qux (T); // { dg-message "note" }
template <typename T> int Qux (T const &); // { dg-message "note" } candidate
-template <typename T> int Bar (T const *const &);
-template <typename T> int Bar (T *const &);
-template <typename T> int Bar (T *);
+template <typename T> int Bar (T const *const &); // { dg-message "note" }
+template <typename T> int Bar (T *const &); // { dg-message "note" } candidate
+template <typename T> int Bar (T *); // { dg-message "note" } candidate
template <typename T> int Baz (T *const &); // { dg-message "note" }
template <typename T> int Baz (T *); // { dg-message "note" } candidate
@@ -24,7 +24,7 @@ template <typename T> int Baz (T *); // { dg-message "note" } candi
int Baz (int const *ptr, int *ptr2)
{
Baz (ptr2); // { dg-error "ambiguous" }
- Bar (ptr2);
+ Bar (ptr2); // { dg-error "ambiguous" }
Foo (ptr2); // { dg-error "ambiguous" }
Qux (ptr2); // { dg-error "ambiguous" }
return 0;