diff mbox

[09/11,PR,gdb/14441] gdb: gdbtypes: add rvalue references to overloading resolution

Message ID 1450661481-31178-10-git-send-email-artemiyv@acm.org
State New
Headers show

Commit Message

Artemiy Volkov Dec. 21, 2015, 1:31 a.m. UTC
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 3 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]

./ChangeLog:

2015-12-20  Artemiy Volkov  <artemiyv@acm.org>

        * gdb/gdbtypes.c (rank_one_type): Implement overloading
        resolution rules regarding rvalue references.
---
 gdb/gdbtypes.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
diff mbox

Patch

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 0cf7d2e..a6d74a1 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -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};
@@ -3464,6 +3466,20 @@  rank_one_type (struct type *parm, struct type *arg, struct value *value)
 {
   struct rank rank = {0,0};
 
+  /* Disallow an rvalue argument to bind to a non-const lvalue reference
+     parameter and an lvalue argument to bind to an rvalue reference
+     parameter. */
+
+  if ((value != NULL)
+      &&
+      ((TYPE_CODE (parm) == TYPE_CODE_REF
+       && !TYPE_CONST (parm->main_type->target_type)
+       && VALUE_LVAL (value) == not_lval)
+      ||
+       (TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF
+       && VALUE_LVAL (value) != not_lval)))
+    return INCOMPATIBLE_TYPE_BADNESS;
+
   if (types_equal (parm, arg))
     return EXACT_MATCH_BADNESS;
 
@@ -3473,6 +3489,36 @@  rank_one_type (struct type *parm, struct type *arg, struct value *value)
   if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
     arg = check_typedef (arg);
 
+  /* 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_REFERENCE (parm) && TYPE_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_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.  */