mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 06:45:56 +08:00
Add rvalue references to overloading resolution
This patch introduces changes to rank_one_type() dealing with ranking an rvalue reference type when selecting a best viable function from a set of candidate functions. The 4 new added rules for rvalue references are: 1) An rvalue argument cannot be bound to a non-const lvalue reference parameter and an lvalue argument cannot be bound to an rvalue reference parameter. [C++11 13.3.3.1.4p3] 2) If a conversion to one type of reference is an identity conversion, and a conversion to the second type of reference is a non-identity conversion, choose the first type. [C++11 13.3.3.2p3] 3) An rvalue should be first tried to bind to an rvalue reference, and then to an lvalue reference. [C++11 13.3.3.2p3] 4) An lvalue reference to a function gets higher priority than an rvalue reference to a function. [C++11 13.3.3.2p3] This patch is not exactly correct. See c++/15372 for tracking overload resolution bugs. gdb/ChangeLog PR gdb/14441 * gdbtypes.c (rank_one_type): Implement overloading resolution rules regarding rvalue references.
This commit is contained in:

committed by
Keith Seitz

parent
aa0061181a
commit
15c0a2a930
@ -1,3 +1,9 @@
|
||||
2017-03-20 Artemiy Volkov <artemiyv@acm.org>
|
||||
|
||||
PR gdb/14441
|
||||
* gdbtypes.c (rank_one_type): Implement overloading
|
||||
resolution rules regarding rvalue references.
|
||||
|
||||
2017-03-20 Artemiy Volkov <artemiyv@acm.org>
|
||||
|
||||
PR gdb/14441
|
||||
|
@ -58,6 +58,8 @@ const struct rank VOID_PTR_CONVERSION_BADNESS = {2,0};
|
||||
const struct rank BOOL_CONVERSION_BADNESS = {3,0};
|
||||
const struct rank BASE_CONVERSION_BADNESS = {2,0};
|
||||
const struct rank REFERENCE_CONVERSION_BADNESS = {2,0};
|
||||
const struct rank LVALUE_REFERENCE_TO_RVALUE_BINDING_BADNESS = {5,0};
|
||||
const struct rank DIFFERENT_REFERENCE_TYPE_BADNESS = {6,0};
|
||||
const struct rank NULL_POINTER_CONVERSION_BADNESS = {2,0};
|
||||
const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
|
||||
const struct rank NS_INTEGER_POINTER_CONVERSION_BADNESS = {3,0};
|
||||
@ -3611,15 +3613,65 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value)
|
||||
{
|
||||
struct rank rank = {0,0};
|
||||
|
||||
if (types_equal (parm, arg))
|
||||
return EXACT_MATCH_BADNESS;
|
||||
|
||||
/* Resolve typedefs */
|
||||
if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
|
||||
parm = check_typedef (parm);
|
||||
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
|
||||
arg = check_typedef (arg);
|
||||
|
||||
if (value != NULL)
|
||||
{
|
||||
/* An rvalue argument cannot be bound to a non-const lvalue
|
||||
reference parameter... */
|
||||
if (VALUE_LVAL (value) == not_lval
|
||||
&& TYPE_CODE (parm) == TYPE_CODE_REF
|
||||
&& !TYPE_CONST (parm->main_type->target_type))
|
||||
return INCOMPATIBLE_TYPE_BADNESS;
|
||||
|
||||
/* ... and an lvalue argument cannot be bound to an rvalue
|
||||
reference parameter. [C++ 13.3.3.1.4p3] */
|
||||
if (VALUE_LVAL (value) != not_lval
|
||||
&& TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF)
|
||||
return INCOMPATIBLE_TYPE_BADNESS;
|
||||
}
|
||||
|
||||
if (types_equal (parm, arg))
|
||||
return EXACT_MATCH_BADNESS;
|
||||
|
||||
/* An lvalue reference to a function should get higher priority than an
|
||||
rvalue reference to a function. */
|
||||
|
||||
if (value != NULL && TYPE_CODE (arg) == TYPE_CODE_RVALUE_REF
|
||||
&& TYPE_CODE (TYPE_TARGET_TYPE (arg)) == TYPE_CODE_FUNC)
|
||||
{
|
||||
return (sum_ranks (rank_one_type (parm,
|
||||
lookup_pointer_type (TYPE_TARGET_TYPE (arg)), NULL),
|
||||
DIFFERENT_REFERENCE_TYPE_BADNESS));
|
||||
}
|
||||
|
||||
/* If a conversion to one type of reference is an identity conversion, and a
|
||||
conversion to the second type of reference is a non-identity conversion,
|
||||
choose the first type. */
|
||||
|
||||
if (value != NULL && TYPE_IS_REFERENCE (parm) && TYPE_IS_REFERENCE (arg)
|
||||
&& TYPE_CODE (parm) != TYPE_CODE (arg))
|
||||
{
|
||||
return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm),
|
||||
TYPE_TARGET_TYPE (arg), NULL), DIFFERENT_REFERENCE_TYPE_BADNESS));
|
||||
}
|
||||
|
||||
/* An rvalue should be first tried to bind to an rvalue reference, and then to
|
||||
an lvalue reference. */
|
||||
|
||||
if (value != NULL && TYPE_CODE (parm) == TYPE_CODE_REF
|
||||
&& VALUE_LVAL (value) == not_lval)
|
||||
{
|
||||
if (TYPE_IS_REFERENCE (arg))
|
||||
arg = TYPE_TARGET_TYPE (arg);
|
||||
return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL),
|
||||
LVALUE_REFERENCE_TO_RVALUE_BINDING_BADNESS));
|
||||
}
|
||||
|
||||
/* See through references, since we can almost make non-references
|
||||
references. */
|
||||
|
||||
|
Reference in New Issue
Block a user