From patchwork Fri Dec 6 07:25:09 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: 36551 Received: (qmail 24578 invoked by alias); 6 Dec 2019 07:25:21 -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 24556 invoked by uid 89); 6 Dec 2019 07:25:20 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=scores, 10, 0, ranking 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; Fri, 06 Dec 2019 07:25:17 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id F29D62039A; Fri, 6 Dec 2019 02:25:15 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id EFBED2012A; Fri, 6 Dec 2019 02:25:11 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id 466C12816F; Fri, 6 Dec 2019 02:25:10 -0500 (EST) X-Gerrit-PatchSet: 2 Date: Fri, 6 Dec 2019 02:25:09 -0500 From: "Sourceware to Gerrit sync (Code Review)" To: Tankut Baris Aktemur , Keith Seitz , Tom Tromey , gdb-patches@sourceware.org Cc: Simon Marchi Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [pushed] gdb: fix overload resolution for see-through references X-Gerrit-Change-Id: I39ae6505ab85ad0bd21915368c82540ceeb3aae9 X-Gerrit-Change-Number: 617 X-Gerrit-ChangeURL: X-Gerrit-Commit: 06acc08f0aa81d0053e9a60bc3bdc1ea3321962e In-Reply-To: References: Reply-To: noreply@gnutoolchain-gerrit.osci.io, tankut.baris.aktemur@intel.com, simon.marchi@polymtl.ca, keiths@redhat.com, tromey@sourceware.org, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-79-g83ff7f88f1 Message-Id: <20191206072510.466C12816F@gnutoolchain-gerrit.osci.io> The original change was created by Tankut Baris Aktemur. 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-12-06 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-12-06 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/ChangeLog M gdb/gdbtypes.c M gdb/gdbtypes.h M gdb/testsuite/ChangeLog M gdb/testsuite/gdb.cp/rvalue-ref-overload.cc M gdb/testsuite/gdb.cp/rvalue-ref-overload.exp 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7646214..2d60712 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2019-12-06 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. + 2019-12-06 Philippe Waroquiers * stack.c (faas_command): Check a command is provided. * thread.c (taas_command, tfaas_command): Likewise. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 4854f49..e226cb7 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}; @@ -4338,10 +4339,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 0dd7333..a1d95e0 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2105,6 +2105,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/ChangeLog b/gdb/testsuite/ChangeLog index 79b124b..adbbd9c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-12-06 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. + 2019-12-06 Philippe Waroquiers * gdb.threads/pthreads.exp: Test taas and tfaas without command. 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"