aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.cp
diff options
context:
space:
mode:
authorTankut Baris Aktemur <tankut.baris.aktemur@intel.com>2019-11-12 15:12:43 +0100
committerTankut Baris Aktemur <tankut.baris.aktemur@intel.com>2019-12-06 08:01:18 +0100
commit06acc08f0aa81d0053e9a60bc3bdc1ea3321962e (patch)
tree95cb7b35042212a65b4428015da39a829b8f164f /gdb/testsuite/gdb.cp
parente0fad1eadfcb68d543cdd96f44dca86364778fa2 (diff)
downloadgdb-06acc08f0aa81d0053e9a60bc3bdc1ea3321962e.zip
gdb-06acc08f0aa81d0053e9a60bc3bdc1ea3321962e.tar.gz
gdb-06acc08f0aa81d0053e9a60bc3bdc1ea3321962e.tar.bz2
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 <tankut.baris.aktemur@intel.com> * 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 <tankut.baris.aktemur@intel.com> * 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
Diffstat (limited to 'gdb/testsuite/gdb.cp')
-rw-r--r--gdb/testsuite/gdb.cp/rvalue-ref-overload.cc9
-rw-r--r--gdb/testsuite/gdb.cp/rvalue-ref-overload.exp4
2 files changed, 13 insertions, 0 deletions
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 @@ public:
int overload1arg (foo_lval_ref);
int overload1arg (foo_rval_ref);
+ int overloadConst (const foo &);
+ int overloadConst (const foo &&);
};
void
@@ -71,6 +73,11 @@ main ()
// 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 @@ foo::~foo () {}
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 @@ cp_test_ptype_class "foo_rr_instance1" "" "class" "foo" \
{ 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 @@ gdb_test "print foo_rr_instance1.overload1arg(static_cast<foo&&>(arg))" \
"\\$\[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"