From 9f74f9cf47ed9d65e65a06378041e9dd5698e49d Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Thu, 8 Apr 2021 08:23:17 -0400
Subject: [PATCH] c++: improve reference binding diagnostic [PR91849]

Here we were complaining about binding the lvalue reference to the rvalue
result of converting from float to int, but didn't mention that conversion.
Talk about the type of the initializer instead.

gcc/cp/ChangeLog:

	PR c++/91849
	* call.c (convert_like_internal): Improve reference diagnostic.

gcc/testsuite/ChangeLog:

	PR c++/91849
	* g++.dg/conversion/pr66211.C: Adjust diagnostic.
	* g++.dg/conversion/ref7.C: New test.
---
 gcc/cp/call.c                             | 15 +++++++++++++--
 gcc/testsuite/g++.dg/conversion/pr66211.C |  2 +-
 gcc/testsuite/g++.dg/conversion/ref7.C    | 17 +++++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/conversion/ref7.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4b81d0ff3331..c9a8c0d305f8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7898,8 +7898,19 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
                         "lvalue of type %qI", totype, extype);
 	    else if (!TYPE_REF_IS_RVALUE (ref_type) && !lvalue_p (expr)
 		     && !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
-	      error_at (loc, "cannot bind non-const lvalue reference of "
-			"type %qH to an rvalue of type %qI", totype, extype);
+	      {
+		conversion *next = next_conversion (convs);
+		if (next->kind == ck_std)
+		  {
+		    next = next_conversion (next);
+		    error_at (loc, "cannot bind non-const lvalue reference of "
+			      "type %qH to a value of type %qI",
+			      totype, next->type);
+		  }
+		else
+		  error_at (loc, "cannot bind non-const lvalue reference of "
+			    "type %qH to an rvalue of type %qI", totype, extype);
+	      }
 	    else if (!reference_compatible_p (TREE_TYPE (totype), extype))
 	      {
 		/* If we're converting from T[] to T[N], don't talk
diff --git a/gcc/testsuite/g++.dg/conversion/pr66211.C b/gcc/testsuite/g++.dg/conversion/pr66211.C
index 770e8a0e20f2..5c1ae13c76d0 100644
--- a/gcc/testsuite/g++.dg/conversion/pr66211.C
+++ b/gcc/testsuite/g++.dg/conversion/pr66211.C
@@ -7,5 +7,5 @@ int main()
 {
   int x = 0;
   double y = 1;
-  f(1 > 0 ? x : y); // { dg-error "cannot bind .* to an rvalue" }
+  f(1 > 0 ? x : y); // { dg-error "cannot bind non-const lvalue reference of type .int&. to a value of type .double" }
 }
diff --git a/gcc/testsuite/g++.dg/conversion/ref7.C b/gcc/testsuite/g++.dg/conversion/ref7.C
new file mode 100644
index 000000000000..99347cb1c27a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ref7.C
@@ -0,0 +1,17 @@
+// PR c++/91849
+
+struct A { operator float(); };
+
+void
+g ()
+{
+  float f = 1.f;
+  int &r = f;			// { dg-error "float" }
+  int &r2 = A();		// { dg-error "float" }
+}
+
+void
+g2 ()
+{
+  int &r = 1.f;			// { dg-error "float" }
+}
-- 
GitLab