From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2126) id 76CEB3858425; Wed, 23 Feb 2022 20:23:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 76CEB3858425 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom Tromey To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Fix bug in C++ overload resolution X-Act-Checkin: binutils-gdb X-Git-Author: Tom Tromey X-Git-Refname: refs/heads/master X-Git-Oldrev: 29ef4c0699e1b46d41ade00ae07a54f979ea21cc X-Git-Newrev: ac03c8d8fd6cf7f9080068589683cb06531879c2 Message-Id: <20220223202334.76CEB3858425@sourceware.org> Date: Wed, 23 Feb 2022 20:23:34 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Feb 2022 20:23:34 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dac03c8d8fd6c= f7f9080068589683cb06531879c2 commit ac03c8d8fd6cf7f9080068589683cb06531879c2 Author: Tom Tromey Date: Fri Feb 18 14:03:03 2022 -0700 Fix bug in C++ overload resolution =20 PR c++/28901 points out a bug in C++ overload resolution. When comparing two overloads, one might be better than the other for certain parameters -- but, if that one also has some invalid conversion, then it should never be considered the better choice. Instead, a valid-but-not-apparently-quite-as-good overload should be preferred. =20 This patch fixes this problem by changing how overload comparisons are done. I don't believe it should affect any currently valid overload resolution; nor should it affect resolutions where all the choices are equally invalid. Diff: --- gdb/gdbtypes.c | 43 +++++++++++++++++++++++++++++++----= ---- gdb/testsuite/gdb.cp/overload.cc | 10 +++++++++ gdb/testsuite/gdb.cp/overload.exp | 3 +++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index a2dbe7551b5..f41d6bd960e 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -44,12 +44,15 @@ #include #include "gmp-utils.h" =20 +/* The value of an invalid conversion badness. */ +#define INVALID_CONVERSION 100 + /* Initialize BADNESS constants. */ =20 -const struct rank LENGTH_MISMATCH_BADNESS =3D {100,0}; +const struct rank LENGTH_MISMATCH_BADNESS =3D {INVALID_CONVERSION,0}; =20 -const struct rank TOO_FEW_PARAMS_BADNESS =3D {100,0}; -const struct rank INCOMPATIBLE_TYPE_BADNESS =3D {100,0}; +const struct rank TOO_FEW_PARAMS_BADNESS =3D {INVALID_CONVERSION,0}; +const struct rank INCOMPATIBLE_TYPE_BADNESS =3D {INVALID_CONVERSION,0}; =20 const struct rank EXACT_MATCH_BADNESS =3D {0,0}; =20 @@ -3966,8 +3969,14 @@ compare_badness (const badness_vector &a, const badn= ess_vector &b) { int i; int tmp; - short found_pos =3D 0; /* any positives in c? */ - short found_neg =3D 0; /* any negatives in c? */ + /* Any positives in comparison? */ + bool found_pos =3D false; + /* Any negatives in comparison? */ + bool found_neg =3D false; + /* Did A have any INVALID_CONVERSION entries. */ + bool a_invalid =3D false; + /* Did B have any INVALID_CONVERSION entries. */ + bool b_invalid =3D false; =20 /* differing sizes =3D> incomparable */ if (a.size () !=3D b.size ()) @@ -3978,12 +3987,27 @@ compare_badness (const badness_vector &a, const bad= ness_vector &b) { tmp =3D compare_ranks (b[i], a[i]); if (tmp > 0) - found_pos =3D 1; + found_pos =3D true; else if (tmp < 0) - found_neg =3D 1; + found_neg =3D true; + if (a[i].rank >=3D INVALID_CONVERSION) + a_invalid =3D true; + if (b[i].rank >=3D INVALID_CONVERSION) + b_invalid =3D true; } =20 - if (found_pos) + /* B will only be considered better than or incomparable to A if + they both have invalid entries, or if neither does. That is, if + A has only valid entries, and B has an invalid entry, then A will + be considered better than B, even if B happens to be better for + some parameter. */ + if (a_invalid !=3D b_invalid) + { + if (a_invalid) + return 3; /* A > B */ + return 2; /* A < B */ + } + else if (found_pos) { if (found_neg) return 1; /* incomparable */ @@ -4742,7 +4766,8 @@ rank_one_type_parm_set (struct type *parm, struct typ= e *arg, struct value *value * Return 0 if they are identical types; * Otherwise, return an integer which corresponds to how compatible * PARM is to ARG. The higher the return value, the worse the match. - * Generally the "bad" conversions are all uniformly assigned a 100. */ + * Generally the "bad" conversions are all uniformly assigned + * INVALID_CONVERSION. */ =20 struct rank rank_one_type (struct type *parm, struct type *arg, struct value *value) diff --git a/gdb/testsuite/gdb.cp/overload.cc b/gdb/testsuite/gdb.cp/overlo= ad.cc index 5c782a46104..ab015721b2b 100644 --- a/gdb/testsuite/gdb.cp/overload.cc +++ b/gdb/testsuite/gdb.cp/overload.cc @@ -93,10 +93,15 @@ class A {}; class B: public A {}; class C: public B {}; class D: C {}; +class E {}; +class F {}; =20 int bar (A) { return 11; } int bar (B) { return 22; } =20 +int bar2 (E &, A &) { return 33; } +int bar2 (F &, B &) { return 44; } + int intintfunc (int x) { return x; } =20 int main ()=20 @@ -119,11 +124,16 @@ int main () B b; C c; D d; + E e; + F f; =20 bar (a); bar (b); bar (c); =20 + bar2 (e, b); + bar2 (f, b); + char *str =3D (char *) "A"; foo foo_instance1(111); foo foo_instance2(222, str); diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overl= oad.exp index 56cd5ac2106..73ca0d2d55c 100644 --- a/gdb/testsuite/gdb.cp/overload.exp +++ b/gdb/testsuite/gdb.cp/overload.exp @@ -259,6 +259,9 @@ gdb_test "print bar(b)" "=3D 22" gdb_test "print bar(c)" "=3D 22" gdb_test "print bar(d)" "=3D 22" =20 +# PR c++/28901 - gdb thought this was ambiguous. +gdb_test "print bar2(e, b)" " =3D 33" + # --- =20 # List overloaded functions.