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
This commit is contained in:
Tankut Baris Aktemur
2019-12-09 17:07:47 +01:00
parent b43315e206
commit 330f1d3825
5 changed files with 30 additions and 5 deletions

View File

@@ -4303,12 +4303,9 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value)
}
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;
}
}