public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for DR 1571 (reference binding)
@ 2014-02-25 21:27 Jason Merrill
  2014-02-26 17:04 ` Jason Merrill
  2014-04-18 18:27 ` Jason Merrill
  0 siblings, 2 replies; 3+ messages in thread
From: Jason Merrill @ 2014-02-25 21:27 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 672 bytes --]

Getting the reference binding rules for C++11 right (in the standard) 
has taken quite a few iterations.  I'm pretty happy with the latest 
wording, which deals with user-defined conversions by recursing on the 
result of the conversion.  This patch implements those rules.  I'm a 
little uncertain about applying this so late in the 4.9 cycle, but I 
think it's a significant improvement to C++11 support.

The second patch fixes a diagnostic issue I noticed while working on 
this: when explaining that a conversion from the result of the 
conversion function failed, the compiler was talking about the 'this' 
parameter.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: dr1571.patch --]
[-- Type: text/x-patch, Size: 4550 bytes --]

commit acf9584aa8d20a2ae1e4b4505f224fc9f937e836
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Feb 11 11:29:18 2014 -0800

    	DR 1571
    	* call.c (reference_binding): Recurse on user-defined conversion.
    	(convert_like_real) [ck_ref_bind]: Explain cv-qual mismatch.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 700099d..32767ec 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1677,20 +1677,37 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
   if (!conv)
     return NULL;
 
-  conv = build_conv (ck_ref_bind, rto, conv);
+  /* Limit this to C++11 mode for GCC 4.9, to be safe.  */
+  if (cxx_dialect >= cxx11 && conv->user_conv_p)
+    {
+      /* If initializing the temporary used a conversion function,
+	 recalculate the second conversion sequence.  */
+      for (conversion *t = conv; t; t = next_conversion (t))
+	if (t->kind == ck_user
+	    && DECL_CONV_FN_P (t->cand->fn))
+	  {
+	    tree ftype = TREE_TYPE (TREE_TYPE (t->cand->fn));
+	    if (TREE_CODE (ftype) != REFERENCE_TYPE)
+	      /* Pretend we start from an xvalue to avoid trouble from
+		 LOOKUP_NO_TEMP_BIND.  */
+	      ftype = cp_build_reference_type (ftype, true);
+	    conversion *new_second
+	      = reference_binding (rto, ftype, NULL_TREE, c_cast_p,
+				   flags|LOOKUP_NO_CONVERSION, complain);
+	    if (!new_second)
+	      return NULL;
+	    conv = merge_conversion_sequences (t, new_second);
+	    break;
+	  }
+    }
+
+  if (conv->kind != ck_ref_bind)
+    conv = build_conv (ck_ref_bind, rto, conv);
+
   /* This reference binding, unlike those above, requires the
      creation of a temporary.  */
   conv->need_temporary_p = true;
-  if (TYPE_REF_IS_RVALUE (rto))
-    {
-      conv->rvaluedness_matches_p = 1;
-      /* In the second case, if the reference is an rvalue reference and
-	 the second standard conversion sequence of the user-defined
-	 conversion sequence includes an lvalue-to-rvalue conversion, the
-	 program is ill-formed.  */
-      if (conv->user_conv_p && next_conversion (conv)->kind == ck_rvalue)
-	conv->bad_p = 1;
-    }
+  conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
 
   return conv;
 }
@@ -6213,12 +6230,25 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 
 	if (convs->bad_p && !next_conversion (convs)->bad_p)
 	  {
-	    gcc_assert (TYPE_REF_IS_RVALUE (ref_type)
-			&& (real_lvalue_p (expr)
-			    || next_conversion(convs)->kind == ck_rvalue));
+	    gcc_assert (TYPE_REF_IS_RVALUE (ref_type));
 
-	    error_at (loc, "cannot bind %qT lvalue to %qT",
-		      TREE_TYPE (expr), totype);
+	    if (real_lvalue_p (expr)
+		|| next_conversion(convs)->kind == ck_rvalue)
+	      error_at (loc, "cannot bind %qT lvalue to %qT",
+			TREE_TYPE (expr), totype);
+	    else if (!reference_compatible_p (totype, TREE_TYPE (expr)))
+	      error_at (loc, "binding %qT to reference of type %qT "
+			"discards qualifiers", TREE_TYPE (expr),totype);
+	    else
+	      gcc_unreachable ();
+	    if (convs->user_conv_p)
+	      for (conversion *t = convs; t; t = next_conversion (t))
+		if (t->kind == ck_user)
+		  {
+		    print_z_candidate (loc, "after user-defined conversion:",
+				       t->cand);
+		    break;
+		  }
 	    if (fn)
 	      inform (input_location,
 		      "initializing argument %P of %q+D", argnum, fn);
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload3.C b/gcc/testsuite/g++.dg/cpp0x/overload3.C
index e521b35..b8f781a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload3.C
@@ -13,5 +13,5 @@ struct wrap
 int main()
 {
   wrap w;
-  f(w);				// { dg-error "lvalue" }
+  f(w);				// { dg-error "" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-init1.C b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
new file mode 100644
index 0000000..2e8d4f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
@@ -0,0 +1,26 @@
+// Core DR 1604/1571/1572
+// { dg-require-effective-target c++11 }
+
+struct Banana { };
+struct Enigma { operator const Banana(); };
+struct Doof { operator Banana&(); };
+void enigmatic() {
+  typedef const Banana ConstBanana;
+  Banana &&banana1 = ConstBanana(); // { dg-error "" }
+  Banana &&banana2 = Enigma();      // { dg-error "" }
+  Banana &&banana3 = Doof();        // { dg-error "" }
+}
+
+class A {
+public:
+  operator volatile int &();
+};
+A a;
+
+const int & ir1a = a.operator volatile int&(); // { dg-error "" }
+const int & ir2a = a;			       // { dg-error "" }
+
+struct X {
+  operator int&();
+} x;
+int&& rri2 = X();		// { dg-error "" }

[-- Attachment #3: conv-err.patch --]
[-- Type: text/x-patch, Size: 1603 bytes --]

commit f84d42ca81f6c327a0356a4dd426a68925db582b
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Feb 11 11:10:04 2014 -0800

    	* call.c (print_conversion_rejection): Handle n_arg of -2.
    	(build_user_type_conversion_1): Pass it.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d3db585..700099d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3180,6 +3180,10 @@ print_conversion_rejection (location_t loc, struct conversion_info *info)
     inform (loc, "  no known conversion for implicit "
 	    "%<this%> parameter from %qT to %qT",
 	    info->from_type, info->to_type);
+  else if (info->n_arg == -2)
+    /* Conversion of conversion function return value failed.  */
+    inform (loc, "  no known conversion from %qT to %qT",
+	    info->from_type, info->to_type);
   else
     inform (loc, "  no known conversion for argument %d from %qT to %qT",
 	    info->n_arg+1, info->from_type, info->to_type);
@@ -3604,7 +3608,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
 	  if (!ics)
 	    {
 	      cand->viable = 0;
-	      cand->reason = arg_conversion_rejection (NULL_TREE, -1,
+	      cand->reason = arg_conversion_rejection (NULL_TREE, -2,
 						       rettype, totype);
 	    }
 	  else if (DECL_NONCONVERTING_P (cand->fn)
@@ -3624,7 +3628,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
 	    {
 	      cand->viable = -1;
 	      cand->reason
-		= bad_arg_conversion_rejection (NULL_TREE, -1,
+		= bad_arg_conversion_rejection (NULL_TREE, -2,
 						rettype, totype);
 	    }
 	  else if (primary_template_instantiation_p (cand->fn)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++ PATCH for DR 1571 (reference binding)
  2014-02-25 21:27 C++ PATCH for DR 1571 (reference binding) Jason Merrill
@ 2014-02-26 17:04 ` Jason Merrill
  2014-04-18 18:27 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2014-02-26 17:04 UTC (permalink / raw)
  To: gcc-patches List

On 02/25/2014 04:27 PM, Jason Merrill wrote:
> I'm a
> little uncertain about applying this so late in the 4.9 cycle, but I
> think it's a significant improvement to C++11 support.

But it broke firefox, so I've reverted it.  I'll try again in stage 1.

Jason


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++ PATCH for DR 1571 (reference binding)
  2014-02-25 21:27 C++ PATCH for DR 1571 (reference binding) Jason Merrill
  2014-02-26 17:04 ` Jason Merrill
@ 2014-04-18 18:27 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2014-04-18 18:27 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 460 bytes --]

On 02/25/2014 04:27 PM, Jason Merrill wrote:
> Getting the reference binding rules for C++11 right (in the standard)
> has taken quite a few iterations.  I'm pretty happy with the latest
> wording, which deals with user-defined conversions by recursing on the
> result of the conversion.  This patch implements those rules.

The earlier patch broke Firefox and was reverted; this patch avoids that 
regression.

Tested x86_64-pc-linux-gnu, applying to trunk.


[-- Attachment #2: dr1571-2.patch --]
[-- Type: text/x-patch, Size: 3013 bytes --]

commit 17d24bce33f71316e2b1f0a4a96deb29d09de0be
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Feb 25 21:27:51 2014 +0000

    	DR 1571
    	* call.c (reference_binding): Recurse on user-defined conversion.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fbd2f83..8c55c32 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1684,20 +1684,30 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
   if (!conv)
     return NULL;
 
+  if (conv->user_conv_p)
+    {
+      /* If initializing the temporary used a conversion function,
+	 recalculate the second conversion sequence.  */
+      for (conversion *t = conv; t; t = next_conversion (t))
+	if (t->kind == ck_user
+	    && DECL_CONV_FN_P (t->cand->fn))
+	  {
+	    tree ftype = TREE_TYPE (TREE_TYPE (t->cand->fn));
+	    int sflags = (flags|LOOKUP_NO_CONVERSION)&~LOOKUP_NO_TEMP_BIND;
+	    conversion *new_second
+	      = reference_binding (rto, ftype, NULL_TREE, c_cast_p,
+				   sflags, complain);
+	    if (!new_second)
+	      return NULL;
+	    return merge_conversion_sequences (t, new_second);
+	  }
+    }
+
   conv = build_conv (ck_ref_bind, rto, conv);
   /* This reference binding, unlike those above, requires the
      creation of a temporary.  */
   conv->need_temporary_p = true;
-  if (TYPE_REF_IS_RVALUE (rto))
-    {
-      conv->rvaluedness_matches_p = 1;
-      /* In the second case, if the reference is an rvalue reference and
-	 the second standard conversion sequence of the user-defined
-	 conversion sequence includes an lvalue-to-rvalue conversion, the
-	 program is ill-formed.  */
-      if (conv->user_conv_p && next_conversion (conv)->kind == ck_rvalue)
-	conv->bad_p = 1;
-    }
+  conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
 
   return conv;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload3.C b/gcc/testsuite/g++.dg/cpp0x/overload3.C
index 2d95783..0eecabd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload3.C
@@ -13,5 +13,5 @@ struct wrap
 int main()
 {
   wrap w;
-  f(w);				// { dg-error "lvalue" }
+  f(w);				// { dg-error "" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-init1.C b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
new file mode 100644
index 0000000..2e8d4f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C
@@ -0,0 +1,26 @@
+// Core DR 1604/1571/1572
+// { dg-require-effective-target c++11 }
+
+struct Banana { };
+struct Enigma { operator const Banana(); };
+struct Doof { operator Banana&(); };
+void enigmatic() {
+  typedef const Banana ConstBanana;
+  Banana &&banana1 = ConstBanana(); // { dg-error "" }
+  Banana &&banana2 = Enigma();      // { dg-error "" }
+  Banana &&banana3 = Doof();        // { dg-error "" }
+}
+
+class A {
+public:
+  operator volatile int &();
+};
+A a;
+
+const int & ir1a = a.operator volatile int&(); // { dg-error "" }
+const int & ir2a = a;			       // { dg-error "" }
+
+struct X {
+  operator int&();
+} x;
+int&& rri2 = X();		// { dg-error "" }

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-04-18 18:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-25 21:27 C++ PATCH for DR 1571 (reference binding) Jason Merrill
2014-02-26 17:04 ` Jason Merrill
2014-04-18 18:27 ` 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).