This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add rvalue references to overloading resolution


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=15c0a2a9305648095f5586a02b5a5017e1643e99

commit 15c0a2a9305648095f5586a02b5a5017e1643e99
Author: Artemiy Volkov <artemiyv@acm.org>
Date:   Mon Mar 20 13:47:57 2017 -0700

    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.

Diff:
---
 gdb/ChangeLog  |  6 ++++++
 gdb/gdbtypes.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c5ebe6f..2f44494 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,12 @@
 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
 	* aarch64-tdep.c (aarch64_type_align)
 	(aarch64_extract_return_value, aarch64_store_return_value): Change
 	lvalue reference type checks to general reference type checks.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index defc00d..6f3aeab 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};
@@ -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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]