C++ify badness_vector, fix leaks

badness_vector is currently an open coded vector.  This reimplements
it as a std::vector.

This fixes a few leaks as well:

 - find_oload_champ is leaking every badness vector calculated bar the
   one returned.

 - bv->rank is always leaked, since callers of rank_function only
   xfree the badness_vector pointer, not bv->rank.

gdb/ChangeLog:
2018-11-21  Pedro Alves  <palves@redhat.com>

	* gdbtypes.c (compare_badness): Change type of parameters to const
	reference.  Adjust to badness_vector being a std::vector now.
	(rank_function): Adjust to badness_vector being a std::vector now.
	* gdbtypes.h (badness_vector): Now a typedef to std::vector.
	(LENGTH_MATCH): Delete.
	(compare_badness): Change type of parameters to const reference.
	(rank_function): Return a badness_vector by value now.
	(find_overload_match): Adjust to badness_vector being a
	std::vector now.  Remove cleanups.
	(find_oload_champ_namespace): 'oload_champ_bv' parameter now a
	badness_vector pointer.
	(find_oload_champ_namespace_loop): 'oload_champ_bv' parameter now
	a badness_vector pointer.  Adjust to badness_vector being a
	std::vector now.  Remove cleanups.
	(find_oload_champ): 'oload_champ_bv' parameter now
	a badness_vector pointer.  Adjust to badness_vector being a
	std::vector now.  Remove cleanups.
This commit is contained in:
Pedro Alves 2018-11-21 11:55:14 +00:00
parent 0891c3cc13
commit 82ceee5014
4 changed files with 74 additions and 84 deletions

View File

@ -1,3 +1,23 @@
2018-11-21 Pedro Alves <palves@redhat.com>
* gdbtypes.c (compare_badness): Change type of parameters to const
reference. Adjust to badness_vector being a std::vector now.
(rank_function): Adjust to badness_vector being a std::vector now.
* gdbtypes.h (badness_vector): Now a typedef to std::vector.
(LENGTH_MATCH): Delete.
(compare_badness): Change type of parameters to const reference.
(rank_function): Return a badness_vector by value now.
(find_overload_match): Adjust to badness_vector being a
std::vector now. Remove cleanups.
(find_oload_champ_namespace): 'oload_champ_bv' parameter now a
badness_vector pointer.
(find_oload_champ_namespace_loop): 'oload_champ_bv' parameter now
a badness_vector pointer. Adjust to badness_vector being a
std::vector now. Remove cleanups.
(find_oload_champ): 'oload_champ_bv' parameter now
a badness_vector pointer. Adjust to badness_vector being a
std::vector now. Remove cleanups.
2018-11-21 Pedro Alves <palves@redhat.com> 2018-11-21 Pedro Alves <palves@redhat.com>
* cp-support.c (sym_return_val_size, sym_return_val_index) * cp-support.c (sym_return_val_size, sym_return_val_index)

View File

@ -3426,21 +3426,21 @@ compare_ranks (struct rank a, struct rank b)
3 => A is worse than B */ 3 => A is worse than B */
int int
compare_badness (struct badness_vector *a, struct badness_vector *b) compare_badness (const badness_vector &a, const badness_vector &b)
{ {
int i; int i;
int tmp; int tmp;
short found_pos = 0; /* any positives in c? */ short found_pos = 0; /* any positives in c? */
short found_neg = 0; /* any negatives in c? */ short found_neg = 0; /* any negatives in c? */
/* differing lengths => incomparable */ /* differing sizes => incomparable */
if (a->length != b->length) if (a.size () != b.size ())
return 1; return 1;
/* Subtract b from a */ /* Subtract b from a */
for (i = 0; i < a->length; i++) for (i = 0; i < a.size (); i++)
{ {
tmp = compare_ranks (b->rank[i], a->rank[i]); tmp = compare_ranks (b[i], a[i]);
if (tmp > 0) if (tmp > 0)
found_pos = 1; found_pos = 1;
else if (tmp < 0) else if (tmp < 0)
@ -3465,19 +3465,16 @@ compare_badness (struct badness_vector *a, struct badness_vector *b)
} }
/* Rank a function by comparing its parameter types (PARMS), to the /* Rank a function by comparing its parameter types (PARMS), to the
types of an argument list (ARGS). Return a pointer to a badness types of an argument list (ARGS). Return the badness vector. This
vector. This has ARGS.size() + 1 entries. */ has ARGS.size() + 1 entries. */
struct badness_vector * badness_vector
rank_function (gdb::array_view<type *> parms, rank_function (gdb::array_view<type *> parms,
gdb::array_view<value *> args) gdb::array_view<value *> args)
{ {
int i; /* add 1 for the length-match rank. */
struct badness_vector *bv = XNEW (struct badness_vector); badness_vector bv;
size_t min_len = std::min (parms.size (), args.size ()); bv.reserve (1 + args.size ());
bv->length = args.size () + 1; /* add 1 for the length-match rank. */
bv->rank = XNEWVEC (struct rank, args.size () + 1);
/* First compare the lengths of the supplied lists. /* First compare the lengths of the supplied lists.
If there is a mismatch, set it to a high value. */ If there is a mismatch, set it to a high value. */
@ -3486,18 +3483,20 @@ rank_function (gdb::array_view<type *> parms,
arguments and ellipsis parameter lists, we should consider those arguments and ellipsis parameter lists, we should consider those
and rank the length-match more finely. */ and rank the length-match more finely. */
LENGTH_MATCH (bv) = (args.size () != parms.size ()) bv.push_back ((args.size () != parms.size ())
? LENGTH_MISMATCH_BADNESS ? LENGTH_MISMATCH_BADNESS
: EXACT_MATCH_BADNESS; : EXACT_MATCH_BADNESS);
/* Now rank all the parameters of the candidate function. */ /* Now rank all the parameters of the candidate function. */
for (i = 1; i <= min_len; i++) size_t min_len = std::min (parms.size (), args.size ());
bv->rank[i] = rank_one_type (parms[i - 1], value_type (args[i - 1]),
args[i - 1]); for (size_t i = 0; i < min_len; i++)
bv.push_back (rank_one_type (parms[i], value_type (args[i]),
args[i]));
/* If more arguments than parameters, add dummy entries. */ /* If more arguments than parameters, add dummy entries. */
for (i = min_len + 1; i <= args.size (); i++) for (size_t i = min_len; i < args.size (); i++)
bv->rank[i] = TOO_FEW_PARAMS_BADNESS; bv.push_back (TOO_FEW_PARAMS_BADNESS);
return bv; return bv;
} }

View File

@ -1095,13 +1095,9 @@ struct rank
short subrank; short subrank;
}; };
/* * Struct used for ranking a function for overload resolution. */ /* * Used for ranking a function for overload resolution. */
struct badness_vector typedef std::vector<rank> badness_vector;
{
int length;
struct rank *rank;
};
/* * GNAT Ada-specific information for various Ada types. */ /* * GNAT Ada-specific information for various Ada types. */
@ -1983,8 +1979,6 @@ extern int is_unique_ancestor (struct type *, struct value *);
/* Overload resolution */ /* Overload resolution */
#define LENGTH_MATCH(bv) ((bv)->rank[0])
/* * Badness if parameter list length doesn't match arg list length. */ /* * Badness if parameter list length doesn't match arg list length. */
extern const struct rank LENGTH_MISMATCH_BADNESS; extern const struct rank LENGTH_MISMATCH_BADNESS;
@ -2043,10 +2037,11 @@ extern const struct rank NS_INTEGER_POINTER_CONVERSION_BADNESS;
extern struct rank sum_ranks (struct rank a, struct rank b); extern struct rank sum_ranks (struct rank a, struct rank b);
extern int compare_ranks (struct rank a, struct rank b); extern int compare_ranks (struct rank a, struct rank b);
extern int compare_badness (struct badness_vector *, struct badness_vector *); extern int compare_badness (const badness_vector &,
const badness_vector &);
extern struct badness_vector *rank_function (gdb::array_view<type *> parms, extern badness_vector rank_function (gdb::array_view<type *> parms,
gdb::array_view<value *> args); gdb::array_view<value *> args);
extern struct rank rank_one_type (struct type *, struct type *, extern struct rank rank_one_type (struct type *, struct type *,
struct value *); struct value *);

View File

@ -57,27 +57,26 @@ static struct value *search_struct_method (const char *, struct value **,
static int find_oload_champ_namespace (gdb::array_view<value *> args, static int find_oload_champ_namespace (gdb::array_view<value *> args,
const char *, const char *, const char *, const char *,
std::vector<symbol *> *oload_syms, std::vector<symbol *> *oload_syms,
struct badness_vector **, badness_vector *,
const int no_adl); const int no_adl);
static int find_oload_champ_namespace_loop (gdb::array_view<value *> args, static int find_oload_champ_namespace_loop (gdb::array_view<value *> args,
const char *, const char *, const char *, const char *,
int, std::vector<symbol *> *oload_syms, int, std::vector<symbol *> *oload_syms,
struct badness_vector **, int *, badness_vector *, int *,
const int no_adl); const int no_adl);
static int find_oload_champ (gdb::array_view<value *> args, int, static int find_oload_champ (gdb::array_view<value *> args, int,
struct fn_field *, struct fn_field *,
const std::vector<xmethod_worker_up> *, const std::vector<xmethod_worker_up> *,
struct symbol **, struct badness_vector **); struct symbol **, badness_vector *);
static int oload_method_static_p (struct fn_field *, int); static int oload_method_static_p (struct fn_field *, int);
enum oload_classification { STANDARD, NON_STANDARD, INCOMPATIBLE }; enum oload_classification { STANDARD, NON_STANDARD, INCOMPATIBLE };
static enum static enum oload_classification classify_oload_match
oload_classification classify_oload_match (struct badness_vector *, (const badness_vector &, int, int);
int, int);
static struct value *value_struct_elt_for_reference (struct type *, static struct value *value_struct_elt_for_reference (struct type *,
int, struct type *, int, struct type *,
@ -2508,10 +2507,10 @@ find_overload_match (gdb::array_view<value *> args,
int ext_method_oload_champ = -1; int ext_method_oload_champ = -1;
/* The measure for the current best match. */ /* The measure for the current best match. */
struct badness_vector *method_badness = NULL; badness_vector method_badness;
struct badness_vector *func_badness = NULL; badness_vector func_badness;
struct badness_vector *ext_method_badness = NULL; badness_vector ext_method_badness;
struct badness_vector *src_method_badness = NULL; badness_vector src_method_badness;
struct value *temp = obj; struct value *temp = obj;
/* For methods, the list of overloaded methods. */ /* For methods, the list of overloaded methods. */
@ -2584,8 +2583,6 @@ find_overload_match (gdb::array_view<value *> args,
src_method_match_quality = classify_oload_match src_method_match_quality = classify_oload_match
(src_method_badness, args.size (), (src_method_badness, args.size (),
oload_method_static_p (fns_ptr, src_method_oload_champ)); oload_method_static_p (fns_ptr, src_method_oload_champ));
make_cleanup (xfree, src_method_badness);
} }
if (!xm_worker_vec.empty ()) if (!xm_worker_vec.empty ())
@ -2594,7 +2591,6 @@ find_overload_match (gdb::array_view<value *> args,
NULL, &ext_method_badness); NULL, &ext_method_badness);
ext_method_match_quality = classify_oload_match (ext_method_badness, ext_method_match_quality = classify_oload_match (ext_method_badness,
args.size (), 0); args.size (), 0);
make_cleanup (xfree, ext_method_badness);
} }
if (src_method_oload_champ >= 0 && ext_method_oload_champ >= 0) if (src_method_oload_champ >= 0 && ext_method_oload_champ >= 0)
@ -2716,8 +2712,6 @@ find_overload_match (gdb::array_view<value *> args,
if (func_oload_champ >= 0) if (func_oload_champ >= 0)
func_match_quality = classify_oload_match (func_badness, func_match_quality = classify_oload_match (func_badness,
args.size (), 0); args.size (), 0);
make_cleanup (xfree, func_badness);
} }
/* Did we find a match ? */ /* Did we find a match ? */
@ -2847,17 +2841,15 @@ find_overload_match (gdb::array_view<value *> args,
/* Find the best overload match, searching for FUNC_NAME in namespaces /* Find the best overload match, searching for FUNC_NAME in namespaces
contained in QUALIFIED_NAME until it either finds a good match or contained in QUALIFIED_NAME until it either finds a good match or
runs out of namespaces. It stores the overloaded functions in runs out of namespaces. It stores the overloaded functions in
*OLOAD_SYMS, and the badness vector in *OLOAD_CHAMP_BV. The *OLOAD_SYMS, and the badness vector in *OLOAD_CHAMP_BV. If NO_ADL,
calling function is responsible for freeing *OLOAD_SYMS and argument dependent lookup is not performned. */
*OLOAD_CHAMP_BV. If NO_ADL, argument dependent lookup is not
performned. */
static int static int
find_oload_champ_namespace (gdb::array_view<value *> args, find_oload_champ_namespace (gdb::array_view<value *> args,
const char *func_name, const char *func_name,
const char *qualified_name, const char *qualified_name,
std::vector<symbol *> *oload_syms, std::vector<symbol *> *oload_syms,
struct badness_vector **oload_champ_bv, badness_vector *oload_champ_bv,
const int no_adl) const int no_adl)
{ {
int oload_champ; int oload_champ;
@ -2876,10 +2868,7 @@ find_oload_champ_namespace (gdb::array_view<value *> args,
how deep we've looked for namespaces, and the champ is stored in how deep we've looked for namespaces, and the champ is stored in
OLOAD_CHAMP. The return value is 1 if the champ is a good one, 0 OLOAD_CHAMP. The return value is 1 if the champ is a good one, 0
if it isn't. Other arguments are the same as in if it isn't. Other arguments are the same as in
find_oload_champ_namespace find_oload_champ_namespace. */
It is the caller's responsibility to free *OLOAD_SYMS and
*OLOAD_CHAMP_BV. */
static int static int
find_oload_champ_namespace_loop (gdb::array_view<value *> args, find_oload_champ_namespace_loop (gdb::array_view<value *> args,
@ -2887,15 +2876,13 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
const char *qualified_name, const char *qualified_name,
int namespace_len, int namespace_len,
std::vector<symbol *> *oload_syms, std::vector<symbol *> *oload_syms,
struct badness_vector **oload_champ_bv, badness_vector *oload_champ_bv,
int *oload_champ, int *oload_champ,
const int no_adl) const int no_adl)
{ {
int next_namespace_len = namespace_len; int next_namespace_len = namespace_len;
int searched_deeper = 0; int searched_deeper = 0;
struct cleanup *old_cleanups;
int new_oload_champ; int new_oload_champ;
struct badness_vector *new_oload_champ_bv;
char *new_namespace; char *new_namespace;
if (next_namespace_len != 0) if (next_namespace_len != 0)
@ -2906,9 +2893,6 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
next_namespace_len += next_namespace_len +=
cp_find_first_component (qualified_name + next_namespace_len); cp_find_first_component (qualified_name + next_namespace_len);
/* Initialize these to values that can safely be xfree'd. */
*oload_champ_bv = NULL;
/* First, see if we have a deeper namespace we can search in. /* First, see if we have a deeper namespace we can search in.
If we get a good match there, use it. */ If we get a good match there, use it. */
@ -2934,7 +2918,6 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
because this overload mechanism only gets called if there's a because this overload mechanism only gets called if there's a
function symbol to start off with.) */ function symbol to start off with.) */
old_cleanups = make_cleanup (xfree, *oload_champ_bv);
new_namespace = (char *) alloca (namespace_len + 1); new_namespace = (char *) alloca (namespace_len + 1);
strncpy (new_namespace, qualified_name, namespace_len); strncpy (new_namespace, qualified_name, namespace_len);
new_namespace[namespace_len] = '\0'; new_namespace[namespace_len] = '\0';
@ -2958,6 +2941,7 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
&new_oload_syms); &new_oload_syms);
} }
badness_vector new_oload_champ_bv;
new_oload_champ = find_oload_champ (args, new_oload_syms.size (), new_oload_champ = find_oload_champ (args, new_oload_syms.size (),
NULL, NULL, new_oload_syms.data (), NULL, NULL, new_oload_syms.data (),
&new_oload_champ_bv); &new_oload_champ_bv);
@ -2974,22 +2958,18 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
{ {
*oload_syms = std::move (new_oload_syms); *oload_syms = std::move (new_oload_syms);
*oload_champ = new_oload_champ; *oload_champ = new_oload_champ;
*oload_champ_bv = new_oload_champ_bv; *oload_champ_bv = std::move (new_oload_champ_bv);
do_cleanups (old_cleanups);
return 1; return 1;
} }
else if (searched_deeper) else if (searched_deeper)
{ {
xfree (new_oload_champ_bv);
discard_cleanups (old_cleanups);
return 0; return 0;
} }
else else
{ {
*oload_syms = std::move (new_oload_syms); *oload_syms = std::move (new_oload_syms);
*oload_champ = new_oload_champ; *oload_champ = new_oload_champ;
*oload_champ_bv = new_oload_champ_bv; *oload_champ_bv = std::move (new_oload_champ_bv);
do_cleanups (old_cleanups);
return 0; return 0;
} }
} }
@ -3003,20 +2983,18 @@ find_oload_champ_namespace_loop (gdb::array_view<value *> args,
or OLOAD_SYMS (whichever is non-NULL) is specified in NUM_FNS. or OLOAD_SYMS (whichever is non-NULL) is specified in NUM_FNS.
Return the index of the best match; store an indication of the Return the index of the best match; store an indication of the
quality of the match in OLOAD_CHAMP_BV. quality of the match in OLOAD_CHAMP_BV. */
It is the caller's responsibility to free *OLOAD_CHAMP_BV. */
static int static int
find_oload_champ (gdb::array_view<value *> args, find_oload_champ (gdb::array_view<value *> args,
int num_fns, struct fn_field *fns_ptr, int num_fns, struct fn_field *fns_ptr,
const std::vector<xmethod_worker_up> *xm_worker_vec, const std::vector<xmethod_worker_up> *xm_worker_vec,
struct symbol **oload_syms, struct symbol **oload_syms,
struct badness_vector **oload_champ_bv) badness_vector *oload_champ_bv)
{ {
int ix; int ix;
/* A measure of how good an overloaded instance is. */ /* A measure of how good an overloaded instance is. */
struct badness_vector *bv; badness_vector bv;
/* Index of best overloaded function. */ /* Index of best overloaded function. */
int oload_champ = -1; int oload_champ = -1;
/* Current ambiguity state for overload resolution. */ /* Current ambiguity state for overload resolution. */
@ -3029,8 +3007,6 @@ find_oload_champ (gdb::array_view<value *> args,
gdb_assert ((fns_ptr != NULL) + (oload_syms != NULL) + (xm_worker_vec != NULL) gdb_assert ((fns_ptr != NULL) + (oload_syms != NULL) + (xm_worker_vec != NULL)
== 1); == 1);
*oload_champ_bv = NULL;
int fn_count = xm_worker_vec != NULL ? xm_worker_vec->size () : num_fns; int fn_count = xm_worker_vec != NULL ? xm_worker_vec->size () : num_fns;
/* Consider each candidate in turn. */ /* Consider each candidate in turn. */
@ -3073,9 +3049,9 @@ find_oload_champ (gdb::array_view<value *> args,
bv = rank_function (parm_types, bv = rank_function (parm_types,
args.slice (static_offset)); args.slice (static_offset));
if (!*oload_champ_bv) if (oload_champ_bv->empty ())
{ {
*oload_champ_bv = bv; *oload_champ_bv = std::move (bv);
oload_champ = 0; oload_champ = 0;
} }
else /* See whether current candidate is better or worse than else /* See whether current candidate is better or worse than
@ -3089,7 +3065,7 @@ find_oload_champ (gdb::array_view<value *> args,
oload_ambiguous = 2; oload_ambiguous = 2;
break; break;
case 2: /* New champion, record details. */ case 2: /* New champion, record details. */
*oload_champ_bv = bv; *oload_champ_bv = std::move (bv);
oload_ambiguous = 0; oload_ambiguous = 0;
oload_champ = ix; oload_champ = ix;
break; break;
@ -3116,7 +3092,7 @@ find_oload_champ (gdb::array_view<value *> args,
for (jj = 0; jj < args.size () - static_offset; jj++) for (jj = 0; jj < args.size () - static_offset; jj++)
fprintf_filtered (gdb_stderr, fprintf_filtered (gdb_stderr,
"...Badness @ %d : %d\n", "...Badness @ %d : %d\n",
jj, bv->rank[jj].rank); jj, bv[jj].rank);
fprintf_filtered (gdb_stderr, "Overload resolution " fprintf_filtered (gdb_stderr, "Overload resolution "
"champion is %d, ambiguous? %d\n", "champion is %d, ambiguous? %d\n",
oload_champ, oload_ambiguous); oload_champ, oload_ambiguous);
@ -3141,7 +3117,7 @@ oload_method_static_p (struct fn_field *fns_ptr, int index)
/* Check how good an overload match OLOAD_CHAMP_BV represents. */ /* Check how good an overload match OLOAD_CHAMP_BV represents. */
static enum oload_classification static enum oload_classification
classify_oload_match (struct badness_vector *oload_champ_bv, classify_oload_match (const badness_vector &oload_champ_bv,
int nargs, int nargs,
int static_offset) int static_offset)
{ {
@ -3152,12 +3128,12 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
{ {
/* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS /* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS
or worse return INCOMPATIBLE. */ or worse return INCOMPATIBLE. */
if (compare_ranks (oload_champ_bv->rank[ix], if (compare_ranks (oload_champ_bv[ix],
INCOMPATIBLE_TYPE_BADNESS) <= 0) INCOMPATIBLE_TYPE_BADNESS) <= 0)
return INCOMPATIBLE; /* Truly mismatched types. */ return INCOMPATIBLE; /* Truly mismatched types. */
/* Otherwise If this conversion is as bad as /* Otherwise If this conversion is as bad as
NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD. */ NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD. */
else if (compare_ranks (oload_champ_bv->rank[ix], else if (compare_ranks (oload_champ_bv[ix],
NS_POINTER_CONVERSION_BADNESS) <= 0) NS_POINTER_CONVERSION_BADNESS) <= 0)
worst = NON_STANDARD; /* Non-standard type conversions worst = NON_STANDARD; /* Non-standard type conversions
needed. */ needed. */