re PR c++/65051 (r210436 regression?)
authorJason Merrill <jason@redhat.com>
Fri, 13 Feb 2015 16:02:31 +0000 (11:02 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 13 Feb 2015 16:02:31 +0000 (11:02 -0500)
PR c++/65051
* call.c (reference_binding): Don't look for bad conversion
if TO is incomplete.

From-SVN: r220685

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/template/overload14.C [new file with mode: 0644]

index a39acaab7593755fb97ff49dfd44a9fe5a63a250..84687715921382ae273c9519b6ca22f6ea95a59c 100644 (file)
@@ -1,3 +1,9 @@
+2015-02-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/65051
+       * call.c (reference_binding): Don't look for bad conversion
+       if TO is incomplete.
+
 2015-02-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/64970
index f2076c67aee090368fee08ab72fcee35470d9ead..2b15185a8951eebbb48065f790fe89e102f60646 100644 (file)
@@ -1694,6 +1694,19 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
      difference in top-level cv-qualification is subsumed by the
      initialization itself and does not constitute a conversion.  */
 
+  /* [dcl.init.ref]
+
+     Otherwise, the reference shall be an lvalue reference to a
+     non-volatile const type, or the reference shall be an rvalue
+     reference.
+
+     We try below to treat this as a bad conversion to improve diagnostics,
+     but if TO is an incomplete class, we need to reject this conversion
+     now to avoid unnecessary instantiation.  */
+  if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto)
+      && !COMPLETE_TYPE_P (to))
+    return NULL;
+
   /* We're generating a temporary now, but don't bind any more in the
      conversion (specifically, don't slice the temporary returned by a
      conversion operator).  */
diff --git a/gcc/testsuite/g++.dg/template/overload14.C b/gcc/testsuite/g++.dg/template/overload14.C
new file mode 100644 (file)
index 0000000..ec2c381
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/65051
+
+template<typename T> struct wrap { typedef T type; };
+template <class T> class rv: public wrap <T>::type {};
+
+template <class value_type>
+struct circular_buffer
+{
+    typedef const value_type& param_value_type;
+    typedef rv< value_type >& rvalue_type;
+
+    void push_back(param_value_type item) {}
+    void push_back(rvalue_type item) {}
+};
+
+union U { int i; char c; };
+
+void f(circular_buffer<U> b, const U& u) { b.push_back(u); }