From patchwork Tue Nov 12 15:23:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 35828 Received: (qmail 14741 invoked by alias); 12 Nov 2019 15:23:14 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 14721 invoked by uid 89); 12 Nov 2019 15:23:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy= X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 12 Nov 2019 15:23:12 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id 170E32047F; Tue, 12 Nov 2019 10:23:08 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [IPv6:2620:52:3:1:5054:ff:fe06:16ca]) by mx1.osci.io (Postfix) with ESMTP id 8AD0020322 for ; Tue, 12 Nov 2019 10:23:07 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id 3505D20AF6 for ; Tue, 12 Nov 2019 10:23:07 -0500 (EST) X-Gerrit-PatchSet: 1 Date: Tue, 12 Nov 2019 10:23:07 -0500 From: "Tankut Baris Aktemur (Code Review)" To: gdb-patches@sourceware.org Message-ID: Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange Subject: [review] gdb: fix overload resolution for see-through references X-Gerrit-Change-Id: I39ae6505ab85ad0bd21915368c82540ceeb3aae9 X-Gerrit-Change-Number: 617 X-Gerrit-ChangeURL: X-Gerrit-Commit: 5f15a22b23765eeb1ca7bcf8b5d3005c7bb68eec References: Reply-To: tankut.baris.aktemur@intel.com, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-76-gf8b6da0ab5 Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/617 ...................................................................... gdb: fix overload resolution for see-through references The overload resolution mechanism assigns badness values to the necessary conversions to be made on types to pick a champion. A badness value consists of a "rank" that scores the conversion and a "subrank" to differentiate conversions of the same kind. An auxiliary function, 'sum_ranks', is used for adding two badness values. In all of its uses, except two, 'sum_ranks' is used for populating the subrank of a badness value. The two exceptions are in 'rank_one_type': ~~~ /* See through references, since we can almost make non-references references. */ if (TYPE_IS_REFERENCE (arg)) return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL), REFERENCE_CONVERSION_BADNESS)); if (TYPE_IS_REFERENCE (parm)) return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL), REFERENCE_CONVERSION_BADNESS)); ~~~ Here, the result of a recursive call is combined with REFERENCE_CONVERSION_BADNESS. This leads to the problem of over-punishment by combining two ranks. Consider this: void an_overloaded_function (const foo &); void an_overloaded_function (const foo &&); ... foo arg; an_overloaded_function(arg); When ranking 'an_overloaded_function (const foo &)', the badness values REFERENCE_CONVERSION_BADNESS and CV_CONVERSION_BADNESS are combined, whereas 'rank_one_type' assigns only the REFERENCE_CONVERSION_BADNESS value to 'an_overloaded_function (const foo &&)' (there is a different execution flow for that). This yields in GDB picking the latter function as the overload champion instead of the former. In fact, the 'rank_one_type' function should have given 'an_overloaded_function (const foo &)' the CV_CONVERSION_BADNESS value, with the see-through referencing increasing the subrank a little bit. This can be achieved by introducing a new badness value, REFERENCE_SEE_THROUGH_BADNESS, which bumps up the subrank only, and using it in the two "exceptional" cases of 'sum_ranks'. gdb/ChangeLog: 2019-11-12 Tankut Baris Aktemur * gdbtypes.h: Define the REFERENCE_SEE_THROUGH_BADNESS value. * gdbtypes.c (rank_one_type): Use REFERENCE_SEE_THROUGH_BADNESS for ranking see-through reference cases. gdb/testsuite/ChangeLog: 2019-11-12 Tankut Baris Aktemur * gdb.cp/rvalue-ref-overload.cc: Add a case that involves both CV and reference conversion for overload resolution. * gdb.cp/rvalue-ref-overload.exp: Test it. Change-Id: I39ae6505ab85ad0bd21915368c82540ceeb3aae9 --- M gdb/gdbtypes.c M gdb/gdbtypes.h M gdb/testsuite/gdb.cp/rvalue-ref-overload.cc M gdb/testsuite/gdb.cp/rvalue-ref-overload.exp 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index fd1c765..2747012 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -60,6 +60,7 @@ 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 REFERENCE_SEE_THROUGH_BADNESS = {0,1}; 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}; @@ -4236,10 +4237,10 @@ if (TYPE_IS_REFERENCE (arg)) return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL), - REFERENCE_CONVERSION_BADNESS)); + REFERENCE_SEE_THROUGH_BADNESS)); if (TYPE_IS_REFERENCE (parm)) return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL), - REFERENCE_CONVERSION_BADNESS)); + REFERENCE_SEE_THROUGH_BADNESS)); if (overload_debug) /* Debugging only. */ fprintf_filtered (gdb_stderr, diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 6d6ff59..590943e 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2072,6 +2072,7 @@ /* * Badness of converting from non-reference to reference. Subrank is the type of reference conversion being done. */ extern const struct rank REFERENCE_CONVERSION_BADNESS; +extern const struct rank REFERENCE_SEE_THROUGH_BADNESS; /* * Conversion to rvalue reference. */ #define REFERENCE_CONVERSION_RVALUE 1 /* * Conversion to const lvalue reference. */ diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc b/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc index fa6cab0..e3111d5 100644 --- a/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc +++ b/gdb/testsuite/gdb.cp/rvalue-ref-overload.cc @@ -35,6 +35,8 @@ int overload1arg (foo_lval_ref); int overload1arg (foo_rval_ref); + int overloadConst (const foo &); + int overloadConst (const foo &&); }; void @@ -71,6 +73,11 @@ // result = 1 + 2 + 3 + 3 = 9 int result = f (i) + f (ci) + f (0) + f (std::move (i)); + /* Overload resolution below requires both a CV-conversion + and reference conversion. */ + int test_const // = 3 + = foo_rr_instance1.overloadConst (arg); + marker1 (); // marker1-returns-here return result; } @@ -84,3 +91,5 @@ int foo::overload1arg (foo_lval_ref arg) { return 1; } int foo::overload1arg (foo_rval_ref arg) { return 2; } +int foo::overloadConst (const foo &arg) { return 3; } +int foo::overloadConst (const foo &&arg) { return 4; } diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp index 61f81b4..693c7ca 100644 --- a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp +++ b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp @@ -49,6 +49,8 @@ { method public "~foo();" } { method public "int overload1arg(foo_lval_ref);" } { method public "int overload1arg(foo_rval_ref);" } + { method public "int overloadConst(const foo &);" } + { method public "int overloadConst(const foo &&);" } } gdb_test "print foo_rr_instance1.overload1arg(arg)" \ @@ -59,6 +61,8 @@ "\\$\[0-9\]+ = 2" \ "print call overloaded func foo && arg" +gdb_test "print foo_rr_instance1.overloadConst(arg)" "3" + # Test lvalue vs rvalue function overloads gdb_test "print f (i)" "= 1" "lvalue reference overload"