[review] gdb: rank an lvalue argument incompatible for an rvalue parameter

Message ID gerrit.1575910688000.I4a6dfc7dac63efa1e3b9f8f391e4b736fbdccdc1@gnutoolchain-gerrit.osci.io
State New, archived
Headers

Commit Message

Simon Marchi (Code Review) Dec. 9, 2019, 4:58 p.m. UTC
  Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/752
......................................................................

gdb: rank an lvalue argument incompatible for an rvalue parameter

Passing an lvalue argument to a function that takes an rvalue parameter
is not allowed per C++ rules.  Consider this function:

    int g (int &&x) { return x; }

Calling g as in

    int i = 5;
    int j = g (i);

is illegal.  For instance, GCC 9.2.1 yields

~~~
test.cpp: In function ‘int main()’:
test.cpp:6:14: error: cannot bind rvalue reference of type ‘int&&’ to
lvalue of type ‘int’
    6 |   int j = g (i);
      |              ^
~~~

GDB currently allows this function call:

~~~
(gdb) print g(i)
$1 = 5
~~~

Fix this by ranking an lvalue argument incompatible with an rvalue
parameter.  The behavior after this patch is:

~~~
(gdb) print g(i)
Cannot resolve function g to any overloaded instance
~~~

Tested with GCC 9.2.1.

gdb/ChangeLog:
2019-12-09  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>

	* gdbtypes.c (rank_one_type): Return INCOMPATIBLE_TYPE_BADNESS
	when ranking an lvalue argument for an rvalue parameter.

gdb/testsuite/ChangeLog:
2019-12-09  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>

	* gdb.cp/rvalue-ref-overload.cc (g): New function that takes
	an rvalue parameter.
	* gdb.cp/rvalue-ref-overload.exp: Test calling it with an lvalue
	parameter.

Change-Id: I4a6dfc7dac63efa1e3b9f8f391e4b736fbdccdc1
---
M gdb/gdbtypes.c
M gdb/testsuite/gdb.cp/rvalue-ref-overload.cc
M gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
3 files changed, 18 insertions(+), 5 deletions(-)
  

Comments

Simon Marchi (Code Review) Dec. 9, 2019, 5:10 p.m. UTC | #1
Simon Marchi has posted comments on this change.

Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/752
......................................................................


Patch Set 1: Code-Review+2

LGTM, thanks for the nice commit message and the test!
  

Patch

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 508628a..0896f71 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -4303,12 +4303,9 @@ 
 	}
       else
 	{
-	  /* Lvalues should prefer lvalue overloads.  */
+	  /* It's illegal to pass an lvalue as an rvalue.  */
 	  if (TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF)
-	    {
-	      rank.subrank = REFERENCE_CONVERSION_RVALUE;
-	      return sum_ranks (rank, REFERENCE_CONVERSION_BADNESS);
-	    }
+	    return INCOMPATIBLE_TYPE_BADNESS;
 	}
     }
 
diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc b/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc
index e3111d5..30634a9 100644
--- a/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc
+++ b/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc
@@ -62,6 +62,12 @@ 
   return 3;
 }
 
+static int
+g (int &&x)
+{
+  return x;
+}
+
 int
 main ()
 {
@@ -78,6 +84,12 @@ 
   int test_const // = 3
     = foo_rr_instance1.overloadConst (arg);
 
+  /* The statement below is illegal: cannot bind rvalue reference of
+     type 'int&&' to lvalue of type 'int'.
+
+     result = g (i); */
+  result = g (5); // this is OK
+
   marker1 (); // marker1-returns-here
   return result;
 }
diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
index e92e901..cac3d4b 100644
--- a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
+++ b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
@@ -66,3 +66,7 @@ 
 
 setup_kfail "c++/15372" "*-*-*"
 gdb_test "print f (3)" "3" "rvalue reference overload"
+
+gdb_test "print g (i)" \
+    "Cannot resolve function g to any overloaded instance" \
+    "passing lvalue arg to rvalue parameter"