From de93309a38afe2a7c0c519c8b69cca7c20d03fbc Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Tue, 29 Oct 2019 17:52:24 -0400 Subject: [PATCH] Clean up ada-lang.h This patch cleans up ada-lang.h: - Some functions just don't exist anymore, remove their declaration - Some functions are implemented in ada-lang.c and only used there, make them static to that file. I moved some functions higher in the file to avoid having to forward-declare them, but the implementations are unchanged. gdb/ChangeLog: * ada-lang.h (GROW_VECT): Move to ada-lang.c. (grow_vect): Remove declaration. (ada_type_of_array): Remove declaration. (ada_update_initial_language): Remove declaration. (ada_fold_name): Remove declaration. (ada_fill_in_ada_prototype): Remove declaration. (user_select_syms): Remove declaration. (get_selections): Remove declaration. (ada_tag_type): Remove declaration. (ada_value_tag): Remove declaration. (ada_is_others_clause): Remove declaration. (ada_in_variant): Remove declaration. (ada_value_struct_elt): Remove declaration. (ada_attribute_name): Remove declaration. (ada_system_address_type): Remove declaration. * ada-lang.c (ada_watch_location_expression): Make static. (GROW_VECT): Move here from ada-lang.h. (grow_vect): Make static. (ada_update_initial_language): Make static. (ada_fold_name): Make static. (ada_type_of_array): Make static. (encoded_ordered_before): Move up. (sort_choices): Move up. (print_signatures): Move up. (ada_print_symbol_signature): Move up. (get_selections): Move up and make static. (user_select_syms): Move up and make static. (ada_value_struct_elt): Move up and make static. (ada_tag_type): Make static. (ada_value_tag): Make static. (ada_is_others_clause): Make static. (ada_in_variant): Make static. (ada_attribute_name): Make static. Change-Id: If0d46ba87d6585ab674c87244068a19e84718fc9 --- gdb/ChangeLog | 36 + gdb/ada-lang.c | 1860 ++++++++++++++++++++++++------------------------ gdb/ada-lang.h | 34 - 3 files changed, 969 insertions(+), 961 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 63c8c57d69d..8c12df0ba50 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2019-10-29 Simon Marchi + + * ada-lang.h (GROW_VECT): Move to ada-lang.c. + (grow_vect): Remove declaration. + (ada_type_of_array): Remove declaration. + (ada_update_initial_language): Remove declaration. + (ada_fold_name): Remove declaration. + (ada_fill_in_ada_prototype): Remove declaration. + (user_select_syms): Remove declaration. + (get_selections): Remove declaration. + (ada_tag_type): Remove declaration. + (ada_value_tag): Remove declaration. + (ada_is_others_clause): Remove declaration. + (ada_in_variant): Remove declaration. + (ada_value_struct_elt): Remove declaration. + (ada_attribute_name): Remove declaration. + (ada_system_address_type): Remove declaration. + * ada-lang.c (ada_watch_location_expression): Make static. + (GROW_VECT): Move here from ada-lang.h. + (grow_vect): Make static. + (ada_update_initial_language): Make static. + (ada_fold_name): Make static. + (ada_type_of_array): Make static. + (encoded_ordered_before): Move up. + (sort_choices): Move up. + (print_signatures): Move up. + (ada_print_symbol_signature): Move up. + (get_selections): Move up and make static. + (user_select_syms): Move up and make static. + (ada_value_struct_elt): Move up and make static. + (ada_tag_type): Make static. + (ada_value_tag): Make static. + (ada_is_others_clause): Make static. + (ada_in_variant): Make static. + (ada_attribute_name): Make static. + 2019-10-29 Simon Marchi * ada-lang.c: Remove includes. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index d08a2644d86..73704907136 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -527,7 +527,7 @@ ada_print_array_index (struct value *index_value, struct ui_file *stream, /* la_watch_location_expression for Ada. */ -gdb::unique_xmalloc_ptr +static gdb::unique_xmalloc_ptr ada_watch_location_expression (struct type *type, CORE_ADDR addr) { type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type))); @@ -536,11 +536,17 @@ ada_watch_location_expression (struct type *type, CORE_ADDR addr) (xstrprintf ("{%s} %s", name.c_str (), core_addr_to_string (addr))); } +/* Assuming V points to an array of S objects, make sure that it contains at + least M objects, updating V and S as necessary. */ + +#define GROW_VECT(v, s, m) \ + if ((s) < (m)) (v) = (char *) grow_vect (v, &(s), m, sizeof *(v)); + /* Assuming VECT points to an array of *SIZE objects of size ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, updating *SIZE as necessary and returning the (new) array. */ -void * +static void * grow_vect (void *vect, size_t *size, size_t min_size, int element_size) { if (*size < min_size) @@ -862,7 +868,7 @@ ada_get_decoded_type (struct type *type) /* If the main program is in Ada, return language_ada, otherwise return LANG (the main program is in Ada iif the adainit symbol is found). */ -enum language +static enum language ada_update_initial_language (enum language lang) { if (lookup_minimal_symbol ("adainit", NULL, NULL).minsym != NULL) @@ -1009,7 +1015,7 @@ ada_encode (const char *decoded) quotes, unfolded, but with the quotes stripped away. Result good to next call. */ -char * +static char * ada_fold_name (const char *name) { static char *fold_buffer = NULL; @@ -1910,7 +1916,8 @@ ada_is_bogus_array_descriptor (struct type *type) the ARR denotes a null array descriptor and BOUNDS is non-zero, returns NULL. The result is simply the type of ARR if ARR is not a descriptor. */ -struct type * + +static struct type * ada_type_of_array (struct value *arr, int bounds) { if (ada_is_constrained_packed_array_type (value_type (arr))) @@ -3140,889 +3147,888 @@ ada_decoded_op_name (enum exp_opcode op) error (_("Could not find operator name for opcode")); } +/* Returns true (non-zero) iff decoded name N0 should appear before N1 + in a listing of choices during disambiguation (see sort_choices, below). + The idea is that overloadings of a subprogram name from the + same package should sort in their source order. We settle for ordering + such symbols by their trailing number (__N or $N). */ -/* Same as evaluate_type (*EXP), but resolves ambiguous symbol - references (marked by OP_VAR_VALUE nodes in which the symbol has an - undefined namespace) and converts operators that are - user-defined into appropriate function calls. If CONTEXT_TYPE is - non-null, it provides a preferred result type [at the moment, only - type void has any effect---causing procedures to be preferred over - functions in calls]. A null CONTEXT_TYPE indicates that a non-void - return type is preferred. May change (expand) *EXP. */ - -static void -resolve (expression_up *expp, int void_context_p, int parse_completion, - innermost_block_tracker *tracker) +static int +encoded_ordered_before (const char *N0, const char *N1) { - struct type *context_type = NULL; - int pc = 0; + if (N1 == NULL) + return 0; + else if (N0 == NULL) + return 1; + else + { + int k0, k1; - if (void_context_p) - context_type = builtin_type ((*expp)->gdbarch)->builtin_void; + for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1) + ; + for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1) + ; + if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000' + && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000') + { + int n0, n1; - resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker); + n0 = k0; + while (N0[n0] == '_' && n0 > 0 && N0[n0 - 1] == '_') + n0 -= 1; + n1 = k1; + while (N1[n1] == '_' && n1 > 0 && N1[n1 - 1] == '_') + n1 -= 1; + if (n0 == n1 && strncmp (N0, N1, n0) == 0) + return (atoi (N0 + k0 + 1) < atoi (N1 + k1 + 1)); + } + return (strcmp (N0, N1) < 0); + } } -/* Resolve the operator of the subexpression beginning at - position *POS of *EXPP. "Resolving" consists of replacing - the symbols that have undefined namespaces in OP_VAR_VALUE nodes - with their resolutions, replacing built-in operators with - function calls to user-defined operators, where appropriate, and, - when DEPROCEDURE_P is non-zero, converting function-valued variables - into parameterless calls. May expand *EXPP. The CONTEXT_TYPE functions - are as in ada_resolve, above. */ +/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by the + encoded names. */ -static struct value * -resolve_subexp (expression_up *expp, int *pos, int deprocedure_p, - struct type *context_type, int parse_completion, - innermost_block_tracker *tracker) +static void +sort_choices (struct block_symbol syms[], int nsyms) { - int pc = *pos; int i; - struct expression *exp; /* Convenience: == *expp. */ - enum exp_opcode op = (*expp)->elts[pc].opcode; - struct value **argvec; /* Vector of operand types (alloca'ed). */ - int nargs; /* Number of operands. */ - int oplen; - argvec = NULL; - nargs = 0; - exp = expp->get (); - - /* Pass one: resolve operands, saving their types and updating *pos, - if needed. */ - switch (op) + for (i = 1; i < nsyms; i += 1) { - case OP_FUNCALL: - if (exp->elts[pc + 3].opcode == OP_VAR_VALUE - && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN) - *pos += 7; - else + struct block_symbol sym = syms[i]; + int j; + + for (j = i - 1; j >= 0; j -= 1) { - *pos += 3; - resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); + if (encoded_ordered_before (SYMBOL_LINKAGE_NAME (syms[j].symbol), + SYMBOL_LINKAGE_NAME (sym.symbol))) + break; + syms[j + 1] = syms[j]; } - nargs = longest_to_int (exp->elts[pc + 1].longconst); - break; + syms[j + 1] = sym; + } +} - case UNOP_ADDR: - *pos += 1; - resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); - break; +/* Whether GDB should display formals and return types for functions in the + overloads selection menu. */ +static bool print_signatures = true; - case UNOP_QUAL: - *pos += 3; - resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type), - parse_completion, tracker); - break; +/* Print the signature for SYM on STREAM according to the FLAGS options. For + all but functions, the signature is just the name of the symbol. For + functions, this is the name of the function, the list of types for formals + and the return type (if any). */ - case OP_ATR_MODULUS: - case OP_ATR_SIZE: - case OP_ATR_TAG: - case OP_ATR_FIRST: - case OP_ATR_LAST: - case OP_ATR_LENGTH: - case OP_ATR_POS: - case OP_ATR_VAL: - case OP_ATR_MIN: - case OP_ATR_MAX: - case TERNOP_IN_RANGE: - case BINOP_IN_BOUNDS: - case UNOP_IN_RANGE: - case OP_AGGREGATE: - case OP_OTHERS: - case OP_CHOICES: - case OP_POSITIONAL: - case OP_DISCRETE_RANGE: - case OP_NAME: - ada_forward_operator_length (exp, pc, &oplen, &nargs); - *pos += oplen; - break; +static void +ada_print_symbol_signature (struct ui_file *stream, struct symbol *sym, + const struct type_print_options *flags) +{ + struct type *type = SYMBOL_TYPE (sym); - case BINOP_ASSIGN: - { - struct value *arg1; + fprintf_filtered (stream, "%s", SYMBOL_PRINT_NAME (sym)); + if (!print_signatures + || type == NULL + || TYPE_CODE (type) != TYPE_CODE_FUNC) + return; - *pos += 1; - arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); - if (arg1 == NULL) - resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker); - else - resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion, - tracker); - break; - } + if (TYPE_NFIELDS (type) > 0) + { + int i; - case UNOP_CAST: - *pos += 3; - nargs = 1; - break; + fprintf_filtered (stream, " ("); + for (i = 0; i < TYPE_NFIELDS (type); ++i) + { + if (i > 0) + fprintf_filtered (stream, "; "); + ada_print_type (TYPE_FIELD_TYPE (type, i), NULL, stream, -1, 0, + flags); + } + fprintf_filtered (stream, ")"); + } + if (TYPE_TARGET_TYPE (type) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + { + fprintf_filtered (stream, " return "); + ada_print_type (TYPE_TARGET_TYPE (type), NULL, stream, -1, 0, flags); + } +} - case BINOP_ADD: - case BINOP_SUB: - case BINOP_MUL: - case BINOP_DIV: - case BINOP_REM: - case BINOP_MOD: - case BINOP_EXP: - case BINOP_CONCAT: - case BINOP_LOGICAL_AND: - case BINOP_LOGICAL_OR: - case BINOP_BITWISE_AND: - case BINOP_BITWISE_IOR: - case BINOP_BITWISE_XOR: +/* Read and validate a set of numeric choices from the user in the + range 0 .. N_CHOICES-1. Place the results in increasing + order in CHOICES[0 .. N-1], and return N. - case BINOP_EQUAL: - case BINOP_NOTEQUAL: - case BINOP_LESS: - case BINOP_GTR: - case BINOP_LEQ: - case BINOP_GEQ: + The user types choices as a sequence of numbers on one line + separated by blanks, encoding them as follows: - case BINOP_REPEAT: - case BINOP_SUBSCRIPT: - case BINOP_COMMA: - *pos += 1; - nargs = 2; - break; + + A choice of 0 means to cancel the selection, throwing an error. + + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1. + + The user chooses k by typing k+IS_ALL_CHOICE+1. - case UNOP_NEG: - case UNOP_PLUS: - case UNOP_LOGICAL_NOT: - case UNOP_ABS: - case UNOP_IND: - *pos += 1; - nargs = 1; - break; + The user is not allowed to choose more than MAX_RESULTS values. - case OP_LONG: - case OP_FLOAT: - case OP_VAR_VALUE: - case OP_VAR_MSYM_VALUE: - *pos += 4; - break; + ANNOTATION_SUFFIX, if present, is used to annotate the input + prompts (for use with the -f switch). */ - case OP_TYPE: - case OP_BOOL: - case OP_LAST: - case OP_INTERNALVAR: - *pos += 3; - break; +static int +get_selections (int *choices, int n_choices, int max_results, + int is_all_choice, const char *annotation_suffix) +{ + char *args; + const char *prompt; + int n_chosen; + int first_choice = is_all_choice ? 2 : 1; - case UNOP_MEMVAL: - *pos += 3; - nargs = 1; - break; - - case OP_REGISTER: - *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); - break; - - case STRUCTOP_STRUCT: - *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); - nargs = 1; - break; - - case TERNOP_SLICE: - *pos += 1; - nargs = 3; - break; + prompt = getenv ("PS2"); + if (prompt == NULL) + prompt = "> "; - case OP_STRING: - break; + args = command_line_input (prompt, annotation_suffix); - default: - error (_("Unexpected operator during name resolution")); - } + if (args == NULL) + error_no_arg (_("one or more choice numbers")); - argvec = XALLOCAVEC (struct value *, nargs + 1); - for (i = 0; i < nargs; i += 1) - argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion, - tracker); - argvec[i] = NULL; - exp = expp->get (); + n_chosen = 0; - /* Pass two: perform any resolution on principal operator. */ - switch (op) + /* Set choices[0 .. n_chosen-1] to the users' choices in ascending + order, as given in args. Choices are validated. */ + while (1) { - default: - break; - - case OP_VAR_VALUE: - if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN) - { - std::vector candidates; - int n_candidates; + char *args2; + int choice, j; - n_candidates = - ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME - (exp->elts[pc + 2].symbol), - exp->elts[pc + 1].block, VAR_DOMAIN, - &candidates); + args = skip_spaces (args); + if (*args == '\0' && n_chosen == 0) + error_no_arg (_("one or more choice numbers")); + else if (*args == '\0') + break; - if (n_candidates > 1) - { - /* Types tend to get re-introduced locally, so if there - are any local symbols that are not types, first filter - out all types. */ - int j; - for (j = 0; j < n_candidates; j += 1) - switch (SYMBOL_CLASS (candidates[j].symbol)) - { - case LOC_REGISTER: - case LOC_ARG: - case LOC_REF_ARG: - case LOC_REGPARM_ADDR: - case LOC_LOCAL: - case LOC_COMPUTED: - goto FoundNonType; - default: - break; - } - FoundNonType: - if (j < n_candidates) - { - j = 0; - while (j < n_candidates) - { - if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF) - { - candidates[j] = candidates[n_candidates - 1]; - n_candidates -= 1; - } - else - j += 1; - } - } - } + choice = strtol (args, &args2, 10); + if (args == args2 || choice < 0 + || choice > n_choices + first_choice - 1) + error (_("Argument must be choice number")); + args = args2; - if (n_candidates == 0) - error (_("No definition found for %s"), - SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); - else if (n_candidates == 1) - i = 0; - else if (deprocedure_p - && !is_nonfunction (candidates.data (), n_candidates)) - { - i = ada_resolve_function - (candidates.data (), n_candidates, NULL, 0, - SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol), - context_type, parse_completion); - if (i < 0) - error (_("Could not find a match for %s"), - SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); - } - else - { - printf_filtered (_("Multiple matches for %s\n"), - SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); - user_select_syms (candidates.data (), n_candidates, 1); - i = 0; - } + if (choice == 0) + error (_("cancelled")); - exp->elts[pc + 1].block = candidates[i].block; - exp->elts[pc + 2].symbol = candidates[i].symbol; - tracker->update (candidates[i]); + if (choice < first_choice) + { + n_chosen = n_choices; + for (j = 0; j < n_choices; j += 1) + choices[j] = j; + break; } + choice -= first_choice; - if (deprocedure_p - && (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 2].symbol)) - == TYPE_CODE_FUNC)) + for (j = n_chosen - 1; j >= 0 && choice < choices[j]; j -= 1) { - replace_operator_with_call (expp, pc, 0, 4, - exp->elts[pc + 2].symbol, - exp->elts[pc + 1].block); - exp = expp->get (); } - break; - - case OP_FUNCALL: - { - if (exp->elts[pc + 3].opcode == OP_VAR_VALUE - && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN) - { - std::vector candidates; - int n_candidates; - - n_candidates = - ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME - (exp->elts[pc + 5].symbol), - exp->elts[pc + 4].block, VAR_DOMAIN, - &candidates); - - if (n_candidates == 1) - i = 0; - else - { - i = ada_resolve_function - (candidates.data (), n_candidates, - argvec, nargs, - SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol), - context_type, parse_completion); - if (i < 0) - error (_("Could not find a match for %s"), - SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol)); - } - exp->elts[pc + 4].block = candidates[i].block; - exp->elts[pc + 5].symbol = candidates[i].symbol; - tracker->update (candidates[i]); - } - } - break; - case BINOP_ADD: - case BINOP_SUB: - case BINOP_MUL: - case BINOP_DIV: - case BINOP_REM: - case BINOP_MOD: - case BINOP_CONCAT: - case BINOP_BITWISE_AND: - case BINOP_BITWISE_IOR: - case BINOP_BITWISE_XOR: - case BINOP_EQUAL: - case BINOP_NOTEQUAL: - case BINOP_LESS: - case BINOP_GTR: - case BINOP_LEQ: - case BINOP_GEQ: - case BINOP_EXP: - case UNOP_NEG: - case UNOP_PLUS: - case UNOP_LOGICAL_NOT: - case UNOP_ABS: - if (possible_user_operator_p (op, argvec)) + if (j < 0 || choice != choices[j]) { - std::vector candidates; - int n_candidates; - - n_candidates = - ada_lookup_symbol_list (ada_decoded_op_name (op), - NULL, VAR_DOMAIN, - &candidates); - - i = ada_resolve_function (candidates.data (), n_candidates, argvec, - nargs, ada_decoded_op_name (op), NULL, - parse_completion); - if (i < 0) - break; + int k; - replace_operator_with_call (expp, pc, nargs, 1, - candidates[i].symbol, - candidates[i].block); - exp = expp->get (); + for (k = n_chosen - 1; k > j; k -= 1) + choices[k + 1] = choices[k]; + choices[j + 1] = choice; + n_chosen += 1; } - break; - - case OP_TYPE: - case OP_REGISTER: - return NULL; } - *pos = pc; - if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE) - return evaluate_var_msym_value (EVAL_AVOID_SIDE_EFFECTS, - exp->elts[pc + 1].objfile, - exp->elts[pc + 2].msymbol); - else - return evaluate_subexp_type (exp, pos); + if (n_chosen > max_results) + error (_("Select no more than %d of the above"), max_results); + + return n_chosen; } -/* Return non-zero if formal type FTYPE matches actual type ATYPE. If - MAY_DEREF is non-zero, the formal may be a pointer and the actual - a non-pointer. */ -/* The term "match" here is rather loose. The match is heuristic and - liberal. */ +/* Given a list of NSYMS symbols in SYMS, select up to MAX_RESULTS>0 + by asking the user (if necessary), returning the number selected, + and setting the first elements of SYMS items. Error if no symbols + selected. */ + +/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought + to be re-integrated one of these days. */ static int -ada_type_match (struct type *ftype, struct type *atype, int may_deref) +user_select_syms (struct block_symbol *syms, int nsyms, int max_results) { - ftype = ada_check_typedef (ftype); - atype = ada_check_typedef (atype); - - if (TYPE_CODE (ftype) == TYPE_CODE_REF) - ftype = TYPE_TARGET_TYPE (ftype); - if (TYPE_CODE (atype) == TYPE_CODE_REF) - atype = TYPE_TARGET_TYPE (atype); - - switch (TYPE_CODE (ftype)) - { - default: - return TYPE_CODE (ftype) == TYPE_CODE (atype); - case TYPE_CODE_PTR: - if (TYPE_CODE (atype) == TYPE_CODE_PTR) - return ada_type_match (TYPE_TARGET_TYPE (ftype), - TYPE_TARGET_TYPE (atype), 0); - else - return (may_deref - && ada_type_match (TYPE_TARGET_TYPE (ftype), atype, 0)); - case TYPE_CODE_INT: - case TYPE_CODE_ENUM: - case TYPE_CODE_RANGE: - switch (TYPE_CODE (atype)) - { - case TYPE_CODE_INT: - case TYPE_CODE_ENUM: - case TYPE_CODE_RANGE: - return 1; - default: - return 0; - } + int i; + int *chosen = XALLOCAVEC (int , nsyms); + int n_chosen; + int first_choice = (max_results == 1) ? 1 : 2; + const char *select_mode = multiple_symbols_select_mode (); - case TYPE_CODE_ARRAY: - return (TYPE_CODE (atype) == TYPE_CODE_ARRAY - || ada_is_array_descriptor_type (atype)); + if (max_results < 1) + error (_("Request to select 0 symbols!")); + if (nsyms <= 1) + return nsyms; - case TYPE_CODE_STRUCT: - if (ada_is_array_descriptor_type (ftype)) - return (TYPE_CODE (atype) == TYPE_CODE_ARRAY - || ada_is_array_descriptor_type (atype)); - else - return (TYPE_CODE (atype) == TYPE_CODE_STRUCT - && !ada_is_array_descriptor_type (atype)); + if (select_mode == multiple_symbols_cancel) + error (_("\ +canceled because the command is ambiguous\n\ +See set/show multiple-symbol.")); - case TYPE_CODE_UNION: - case TYPE_CODE_FLT: - return (TYPE_CODE (atype) == TYPE_CODE (ftype)); - } -} + /* If select_mode is "all", then return all possible symbols. + Only do that if more than one symbol can be selected, of course. + Otherwise, display the menu as usual. */ + if (select_mode == multiple_symbols_all && max_results > 1) + return nsyms; -/* Return non-zero if the formals of FUNC "sufficiently match" the - vector of actual argument types ACTUALS of size N_ACTUALS. FUNC - may also be an enumeral, in which case it is treated as a 0- - argument function. */ + printf_filtered (_("[0] cancel\n")); + if (max_results > 1) + printf_filtered (_("[1] all\n")); -static int -ada_args_match (struct symbol *func, struct value **actuals, int n_actuals) -{ - int i; - struct type *func_type = SYMBOL_TYPE (func); + sort_choices (syms, nsyms); - if (SYMBOL_CLASS (func) == LOC_CONST - && TYPE_CODE (func_type) == TYPE_CODE_ENUM) - return (n_actuals == 0); - else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC) - return 0; + for (i = 0; i < nsyms; i += 1) + { + if (syms[i].symbol == NULL) + continue; - if (TYPE_NFIELDS (func_type) != n_actuals) - return 0; + if (SYMBOL_CLASS (syms[i].symbol) == LOC_BLOCK) + { + struct symtab_and_line sal = + find_function_start_sal (syms[i].symbol, 1); - for (i = 0; i < n_actuals; i += 1) - { - if (actuals[i] == NULL) - return 0; + printf_filtered ("[%d] ", i + first_choice); + ada_print_symbol_signature (gdb_stdout, syms[i].symbol, + &type_print_raw_options); + if (sal.symtab == NULL) + printf_filtered (_(" at %p[%p]:%d\n"), + metadata_style.style ().ptr (), nullptr, sal.line); + else + printf_filtered + (_(" at %ps:%d\n"), + styled_string (file_name_style.style (), + symtab_to_filename_for_display (sal.symtab)), + sal.line); + continue; + } else { - struct type *ftype = ada_check_typedef (TYPE_FIELD_TYPE (func_type, - i)); - struct type *atype = ada_check_typedef (value_type (actuals[i])); + int is_enumeral = + (SYMBOL_CLASS (syms[i].symbol) == LOC_CONST + && SYMBOL_TYPE (syms[i].symbol) != NULL + && TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) == TYPE_CODE_ENUM); + struct symtab *symtab = NULL; - if (!ada_type_match (ftype, atype, 1)) - return 0; + if (SYMBOL_OBJFILE_OWNED (syms[i].symbol)) + symtab = symbol_symtab (syms[i].symbol); + + if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL) + { + printf_filtered ("[%d] ", i + first_choice); + ada_print_symbol_signature (gdb_stdout, syms[i].symbol, + &type_print_raw_options); + printf_filtered (_(" at %s:%d\n"), + symtab_to_filename_for_display (symtab), + SYMBOL_LINE (syms[i].symbol)); + } + else if (is_enumeral + && TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL) + { + printf_filtered (("[%d] "), i + first_choice); + ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL, + gdb_stdout, -1, 0, &type_print_raw_options); + printf_filtered (_("'(%s) (enumeral)\n"), + SYMBOL_PRINT_NAME (syms[i].symbol)); + } + else + { + printf_filtered ("[%d] ", i + first_choice); + ada_print_symbol_signature (gdb_stdout, syms[i].symbol, + &type_print_raw_options); + + if (symtab != NULL) + printf_filtered (is_enumeral + ? _(" in %s (enumeral)\n") + : _(" at %s:?\n"), + symtab_to_filename_for_display (symtab)); + else + printf_filtered (is_enumeral + ? _(" (enumeral)\n") + : _(" at ?\n")); + } } } - return 1; -} - -/* False iff function type FUNC_TYPE definitely does not produce a value - compatible with type CONTEXT_TYPE. Conservatively returns 1 if - FUNC_TYPE is not a valid function type with a non-null return type - or an enumerated type. A null CONTEXT_TYPE indicates any non-void type. */ -static int -return_match (struct type *func_type, struct type *context_type) -{ - struct type *return_type; + n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1, + "overload-choice"); - if (func_type == NULL) - return 1; + for (i = 0; i < n_chosen; i += 1) + syms[i] = syms[chosen[i]]; - if (TYPE_CODE (func_type) == TYPE_CODE_FUNC) - return_type = get_base_type (TYPE_TARGET_TYPE (func_type)); - else - return_type = get_base_type (func_type); - if (return_type == NULL) - return 1; + return n_chosen; +} - context_type = get_base_type (context_type); +/* Same as evaluate_type (*EXP), but resolves ambiguous symbol + references (marked by OP_VAR_VALUE nodes in which the symbol has an + undefined namespace) and converts operators that are + user-defined into appropriate function calls. If CONTEXT_TYPE is + non-null, it provides a preferred result type [at the moment, only + type void has any effect---causing procedures to be preferred over + functions in calls]. A null CONTEXT_TYPE indicates that a non-void + return type is preferred. May change (expand) *EXP. */ - if (TYPE_CODE (return_type) == TYPE_CODE_ENUM) - return context_type == NULL || return_type == context_type; - else if (context_type == NULL) - return TYPE_CODE (return_type) != TYPE_CODE_VOID; - else - return TYPE_CODE (return_type) == TYPE_CODE (context_type); -} +static void +resolve (expression_up *expp, int void_context_p, int parse_completion, + innermost_block_tracker *tracker) +{ + struct type *context_type = NULL; + int pc = 0; + if (void_context_p) + context_type = builtin_type ((*expp)->gdbarch)->builtin_void; -/* Returns the index in SYMS[0..NSYMS-1] that contains the symbol for the - function (if any) that matches the types of the NARGS arguments in - ARGS. If CONTEXT_TYPE is non-null and there is at least one match - that returns that type, then eliminate matches that don't. If - CONTEXT_TYPE is void and there is at least one match that does not - return void, eliminate all matches that do. + resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker); +} - Asks the user if there is more than one match remaining. Returns -1 - if there is no such symbol or none is selected. NAME is used - solely for messages. May re-arrange and modify SYMS in - the process; the index returned is for the modified vector. */ +/* Resolve the operator of the subexpression beginning at + position *POS of *EXPP. "Resolving" consists of replacing + the symbols that have undefined namespaces in OP_VAR_VALUE nodes + with their resolutions, replacing built-in operators with + function calls to user-defined operators, where appropriate, and, + when DEPROCEDURE_P is non-zero, converting function-valued variables + into parameterless calls. May expand *EXPP. The CONTEXT_TYPE functions + are as in ada_resolve, above. */ -static int -ada_resolve_function (struct block_symbol syms[], - int nsyms, struct value **args, int nargs, - const char *name, struct type *context_type, - int parse_completion) +static struct value * +resolve_subexp (expression_up *expp, int *pos, int deprocedure_p, + struct type *context_type, int parse_completion, + innermost_block_tracker *tracker) { - int fallback; - int k; - int m; /* Number of hits */ + int pc = *pos; + int i; + struct expression *exp; /* Convenience: == *expp. */ + enum exp_opcode op = (*expp)->elts[pc].opcode; + struct value **argvec; /* Vector of operand types (alloca'ed). */ + int nargs; /* Number of operands. */ + int oplen; - m = 0; - /* In the first pass of the loop, we only accept functions matching - context_type. If none are found, we add a second pass of the loop - where every function is accepted. */ - for (fallback = 0; m == 0 && fallback < 2; fallback++) - { - for (k = 0; k < nsyms; k += 1) - { - struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol)); + argvec = NULL; + nargs = 0; + exp = expp->get (); - if (ada_args_match (syms[k].symbol, args, nargs) - && (fallback || return_match (type, context_type))) - { - syms[m] = syms[k]; - m += 1; - } + /* Pass one: resolve operands, saving their types and updating *pos, + if needed. */ + switch (op) + { + case OP_FUNCALL: + if (exp->elts[pc + 3].opcode == OP_VAR_VALUE + && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN) + *pos += 7; + else + { + *pos += 3; + resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); } - } + nargs = longest_to_int (exp->elts[pc + 1].longconst); + break; - /* If we got multiple matches, ask the user which one to use. Don't do this - interactive thing during completion, though, as the purpose of the - completion is providing a list of all possible matches. Prompting the - user to filter it down would be completely unexpected in this case. */ - if (m == 0) - return -1; - else if (m > 1 && !parse_completion) - { - printf_filtered (_("Multiple matches for %s\n"), name); - user_select_syms (syms, m, 1); - return 0; + case UNOP_ADDR: + *pos += 1; + resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); + break; + + case UNOP_QUAL: + *pos += 3; + resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type), + parse_completion, tracker); + break; + + case OP_ATR_MODULUS: + case OP_ATR_SIZE: + case OP_ATR_TAG: + case OP_ATR_FIRST: + case OP_ATR_LAST: + case OP_ATR_LENGTH: + case OP_ATR_POS: + case OP_ATR_VAL: + case OP_ATR_MIN: + case OP_ATR_MAX: + case TERNOP_IN_RANGE: + case BINOP_IN_BOUNDS: + case UNOP_IN_RANGE: + case OP_AGGREGATE: + case OP_OTHERS: + case OP_CHOICES: + case OP_POSITIONAL: + case OP_DISCRETE_RANGE: + case OP_NAME: + ada_forward_operator_length (exp, pc, &oplen, &nargs); + *pos += oplen; + break; + + case BINOP_ASSIGN: + { + struct value *arg1; + + *pos += 1; + arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker); + if (arg1 == NULL) + resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker); + else + resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion, + tracker); + break; + } + + case UNOP_CAST: + *pos += 3; + nargs = 1; + break; + + case BINOP_ADD: + case BINOP_SUB: + case BINOP_MUL: + case BINOP_DIV: + case BINOP_REM: + case BINOP_MOD: + case BINOP_EXP: + case BINOP_CONCAT: + case BINOP_LOGICAL_AND: + case BINOP_LOGICAL_OR: + case BINOP_BITWISE_AND: + case BINOP_BITWISE_IOR: + case BINOP_BITWISE_XOR: + + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_LEQ: + case BINOP_GEQ: + + case BINOP_REPEAT: + case BINOP_SUBSCRIPT: + case BINOP_COMMA: + *pos += 1; + nargs = 2; + break; + + case UNOP_NEG: + case UNOP_PLUS: + case UNOP_LOGICAL_NOT: + case UNOP_ABS: + case UNOP_IND: + *pos += 1; + nargs = 1; + break; + + case OP_LONG: + case OP_FLOAT: + case OP_VAR_VALUE: + case OP_VAR_MSYM_VALUE: + *pos += 4; + break; + + case OP_TYPE: + case OP_BOOL: + case OP_LAST: + case OP_INTERNALVAR: + *pos += 3; + break; + + case UNOP_MEMVAL: + *pos += 3; + nargs = 1; + break; + + case OP_REGISTER: + *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); + break; + + case STRUCTOP_STRUCT: + *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); + nargs = 1; + break; + + case TERNOP_SLICE: + *pos += 1; + nargs = 3; + break; + + case OP_STRING: + break; + + default: + error (_("Unexpected operator during name resolution")); } - return 0; -} -/* Returns true (non-zero) iff decoded name N0 should appear before N1 - in a listing of choices during disambiguation (see sort_choices, below). - The idea is that overloadings of a subprogram name from the - same package should sort in their source order. We settle for ordering - such symbols by their trailing number (__N or $N). */ + argvec = XALLOCAVEC (struct value *, nargs + 1); + for (i = 0; i < nargs; i += 1) + argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion, + tracker); + argvec[i] = NULL; + exp = expp->get (); -static int -encoded_ordered_before (const char *N0, const char *N1) -{ - if (N1 == NULL) - return 0; - else if (N0 == NULL) - return 1; - else + /* Pass two: perform any resolution on principal operator. */ + switch (op) { - int k0, k1; + default: + break; - for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1) - ; - for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1) - ; - if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000' - && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000') + case OP_VAR_VALUE: + if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN) { - int n0, n1; + std::vector candidates; + int n_candidates; - n0 = k0; - while (N0[n0] == '_' && n0 > 0 && N0[n0 - 1] == '_') - n0 -= 1; - n1 = k1; - while (N1[n1] == '_' && n1 > 0 && N1[n1 - 1] == '_') - n1 -= 1; - if (n0 == n1 && strncmp (N0, N1, n0) == 0) - return (atoi (N0 + k0 + 1) < atoi (N1 + k1 + 1)); - } - return (strcmp (N0, N1) < 0); - } -} + n_candidates = + ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME + (exp->elts[pc + 2].symbol), + exp->elts[pc + 1].block, VAR_DOMAIN, + &candidates); -/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by the - encoded names. */ + if (n_candidates > 1) + { + /* Types tend to get re-introduced locally, so if there + are any local symbols that are not types, first filter + out all types. */ + int j; + for (j = 0; j < n_candidates; j += 1) + switch (SYMBOL_CLASS (candidates[j].symbol)) + { + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM_ADDR: + case LOC_LOCAL: + case LOC_COMPUTED: + goto FoundNonType; + default: + break; + } + FoundNonType: + if (j < n_candidates) + { + j = 0; + while (j < n_candidates) + { + if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF) + { + candidates[j] = candidates[n_candidates - 1]; + n_candidates -= 1; + } + else + j += 1; + } + } + } -static void -sort_choices (struct block_symbol syms[], int nsyms) -{ - int i; + if (n_candidates == 0) + error (_("No definition found for %s"), + SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); + else if (n_candidates == 1) + i = 0; + else if (deprocedure_p + && !is_nonfunction (candidates.data (), n_candidates)) + { + i = ada_resolve_function + (candidates.data (), n_candidates, NULL, 0, + SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol), + context_type, parse_completion); + if (i < 0) + error (_("Could not find a match for %s"), + SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); + } + else + { + printf_filtered (_("Multiple matches for %s\n"), + SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol)); + user_select_syms (candidates.data (), n_candidates, 1); + i = 0; + } - for (i = 1; i < nsyms; i += 1) - { - struct block_symbol sym = syms[i]; - int j; + exp->elts[pc + 1].block = candidates[i].block; + exp->elts[pc + 2].symbol = candidates[i].symbol; + tracker->update (candidates[i]); + } - for (j = i - 1; j >= 0; j -= 1) + if (deprocedure_p + && (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 2].symbol)) + == TYPE_CODE_FUNC)) { - if (encoded_ordered_before (SYMBOL_LINKAGE_NAME (syms[j].symbol), - SYMBOL_LINKAGE_NAME (sym.symbol))) - break; - syms[j + 1] = syms[j]; + replace_operator_with_call (expp, pc, 0, 4, + exp->elts[pc + 2].symbol, + exp->elts[pc + 1].block); + exp = expp->get (); } - syms[j + 1] = sym; - } -} + break; + + case OP_FUNCALL: + { + if (exp->elts[pc + 3].opcode == OP_VAR_VALUE + && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN) + { + std::vector candidates; + int n_candidates; + + n_candidates = + ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME + (exp->elts[pc + 5].symbol), + exp->elts[pc + 4].block, VAR_DOMAIN, + &candidates); -/* Whether GDB should display formals and return types for functions in the - overloads selection menu. */ -static bool print_signatures = true; + if (n_candidates == 1) + i = 0; + else + { + i = ada_resolve_function + (candidates.data (), n_candidates, + argvec, nargs, + SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol), + context_type, parse_completion); + if (i < 0) + error (_("Could not find a match for %s"), + SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol)); + } -/* Print the signature for SYM on STREAM according to the FLAGS options. For - all but functions, the signature is just the name of the symbol. For - functions, this is the name of the function, the list of types for formals - and the return type (if any). */ + exp->elts[pc + 4].block = candidates[i].block; + exp->elts[pc + 5].symbol = candidates[i].symbol; + tracker->update (candidates[i]); + } + } + break; + case BINOP_ADD: + case BINOP_SUB: + case BINOP_MUL: + case BINOP_DIV: + case BINOP_REM: + case BINOP_MOD: + case BINOP_CONCAT: + case BINOP_BITWISE_AND: + case BINOP_BITWISE_IOR: + case BINOP_BITWISE_XOR: + case BINOP_EQUAL: + case BINOP_NOTEQUAL: + case BINOP_LESS: + case BINOP_GTR: + case BINOP_LEQ: + case BINOP_GEQ: + case BINOP_EXP: + case UNOP_NEG: + case UNOP_PLUS: + case UNOP_LOGICAL_NOT: + case UNOP_ABS: + if (possible_user_operator_p (op, argvec)) + { + std::vector candidates; + int n_candidates; -static void -ada_print_symbol_signature (struct ui_file *stream, struct symbol *sym, - const struct type_print_options *flags) -{ - struct type *type = SYMBOL_TYPE (sym); + n_candidates = + ada_lookup_symbol_list (ada_decoded_op_name (op), + NULL, VAR_DOMAIN, + &candidates); - fprintf_filtered (stream, "%s", SYMBOL_PRINT_NAME (sym)); - if (!print_signatures - || type == NULL - || TYPE_CODE (type) != TYPE_CODE_FUNC) - return; + i = ada_resolve_function (candidates.data (), n_candidates, argvec, + nargs, ada_decoded_op_name (op), NULL, + parse_completion); + if (i < 0) + break; - if (TYPE_NFIELDS (type) > 0) - { - int i; + replace_operator_with_call (expp, pc, nargs, 1, + candidates[i].symbol, + candidates[i].block); + exp = expp->get (); + } + break; - fprintf_filtered (stream, " ("); - for (i = 0; i < TYPE_NFIELDS (type); ++i) - { - if (i > 0) - fprintf_filtered (stream, "; "); - ada_print_type (TYPE_FIELD_TYPE (type, i), NULL, stream, -1, 0, - flags); - } - fprintf_filtered (stream, ")"); - } - if (TYPE_TARGET_TYPE (type) != NULL - && TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) - { - fprintf_filtered (stream, " return "); - ada_print_type (TYPE_TARGET_TYPE (type), NULL, stream, -1, 0, flags); + case OP_TYPE: + case OP_REGISTER: + return NULL; } -} -/* Given a list of NSYMS symbols in SYMS, select up to MAX_RESULTS>0 - by asking the user (if necessary), returning the number selected, - and setting the first elements of SYMS items. Error if no symbols - selected. */ + *pos = pc; + if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE) + return evaluate_var_msym_value (EVAL_AVOID_SIDE_EFFECTS, + exp->elts[pc + 1].objfile, + exp->elts[pc + 2].msymbol); + else + return evaluate_subexp_type (exp, pos); +} -/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought - to be re-integrated one of these days. */ +/* Return non-zero if formal type FTYPE matches actual type ATYPE. If + MAY_DEREF is non-zero, the formal may be a pointer and the actual + a non-pointer. */ +/* The term "match" here is rather loose. The match is heuristic and + liberal. */ -int -user_select_syms (struct block_symbol *syms, int nsyms, int max_results) +static int +ada_type_match (struct type *ftype, struct type *atype, int may_deref) { - int i; - int *chosen = XALLOCAVEC (int , nsyms); - int n_chosen; - int first_choice = (max_results == 1) ? 1 : 2; - const char *select_mode = multiple_symbols_select_mode (); - - if (max_results < 1) - error (_("Request to select 0 symbols!")); - if (nsyms <= 1) - return nsyms; - - if (select_mode == multiple_symbols_cancel) - error (_("\ -canceled because the command is ambiguous\n\ -See set/show multiple-symbol.")); - - /* If select_mode is "all", then return all possible symbols. - Only do that if more than one symbol can be selected, of course. - Otherwise, display the menu as usual. */ - if (select_mode == multiple_symbols_all && max_results > 1) - return nsyms; - - printf_filtered (_("[0] cancel\n")); - if (max_results > 1) - printf_filtered (_("[1] all\n")); + ftype = ada_check_typedef (ftype); + atype = ada_check_typedef (atype); - sort_choices (syms, nsyms); + if (TYPE_CODE (ftype) == TYPE_CODE_REF) + ftype = TYPE_TARGET_TYPE (ftype); + if (TYPE_CODE (atype) == TYPE_CODE_REF) + atype = TYPE_TARGET_TYPE (atype); - for (i = 0; i < nsyms; i += 1) + switch (TYPE_CODE (ftype)) { - if (syms[i].symbol == NULL) - continue; - - if (SYMBOL_CLASS (syms[i].symbol) == LOC_BLOCK) - { - struct symtab_and_line sal = - find_function_start_sal (syms[i].symbol, 1); - - printf_filtered ("[%d] ", i + first_choice); - ada_print_symbol_signature (gdb_stdout, syms[i].symbol, - &type_print_raw_options); - if (sal.symtab == NULL) - printf_filtered (_(" at %p[%p]:%d\n"), - metadata_style.style ().ptr (), nullptr, sal.line); - else - printf_filtered - (_(" at %ps:%d\n"), - styled_string (file_name_style.style (), - symtab_to_filename_for_display (sal.symtab)), - sal.line); - continue; - } + default: + return TYPE_CODE (ftype) == TYPE_CODE (atype); + case TYPE_CODE_PTR: + if (TYPE_CODE (atype) == TYPE_CODE_PTR) + return ada_type_match (TYPE_TARGET_TYPE (ftype), + TYPE_TARGET_TYPE (atype), 0); else + return (may_deref + && ada_type_match (TYPE_TARGET_TYPE (ftype), atype, 0)); + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + switch (TYPE_CODE (atype)) { - int is_enumeral = - (SYMBOL_CLASS (syms[i].symbol) == LOC_CONST - && SYMBOL_TYPE (syms[i].symbol) != NULL - && TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) == TYPE_CODE_ENUM); - struct symtab *symtab = NULL; - - if (SYMBOL_OBJFILE_OWNED (syms[i].symbol)) - symtab = symbol_symtab (syms[i].symbol); - - if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL) - { - printf_filtered ("[%d] ", i + first_choice); - ada_print_symbol_signature (gdb_stdout, syms[i].symbol, - &type_print_raw_options); - printf_filtered (_(" at %s:%d\n"), - symtab_to_filename_for_display (symtab), - SYMBOL_LINE (syms[i].symbol)); - } - else if (is_enumeral - && TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL) - { - printf_filtered (("[%d] "), i + first_choice); - ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL, - gdb_stdout, -1, 0, &type_print_raw_options); - printf_filtered (_("'(%s) (enumeral)\n"), - SYMBOL_PRINT_NAME (syms[i].symbol)); - } - else - { - printf_filtered ("[%d] ", i + first_choice); - ada_print_symbol_signature (gdb_stdout, syms[i].symbol, - &type_print_raw_options); - - if (symtab != NULL) - printf_filtered (is_enumeral - ? _(" in %s (enumeral)\n") - : _(" at %s:?\n"), - symtab_to_filename_for_display (symtab)); - else - printf_filtered (is_enumeral - ? _(" (enumeral)\n") - : _(" at ?\n")); - } + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + return 1; + default: + return 0; } - } - n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1, - "overload-choice"); + case TYPE_CODE_ARRAY: + return (TYPE_CODE (atype) == TYPE_CODE_ARRAY + || ada_is_array_descriptor_type (atype)); - for (i = 0; i < n_chosen; i += 1) - syms[i] = syms[chosen[i]]; + case TYPE_CODE_STRUCT: + if (ada_is_array_descriptor_type (ftype)) + return (TYPE_CODE (atype) == TYPE_CODE_ARRAY + || ada_is_array_descriptor_type (atype)); + else + return (TYPE_CODE (atype) == TYPE_CODE_STRUCT + && !ada_is_array_descriptor_type (atype)); - return n_chosen; + case TYPE_CODE_UNION: + case TYPE_CODE_FLT: + return (TYPE_CODE (atype) == TYPE_CODE (ftype)); + } } -/* Read and validate a set of numeric choices from the user in the - range 0 .. N_CHOICES-1. Place the results in increasing - order in CHOICES[0 .. N-1], and return N. +/* Return non-zero if the formals of FUNC "sufficiently match" the + vector of actual argument types ACTUALS of size N_ACTUALS. FUNC + may also be an enumeral, in which case it is treated as a 0- + argument function. */ - The user types choices as a sequence of numbers on one line - separated by blanks, encoding them as follows: +static int +ada_args_match (struct symbol *func, struct value **actuals, int n_actuals) +{ + int i; + struct type *func_type = SYMBOL_TYPE (func); - + A choice of 0 means to cancel the selection, throwing an error. - + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1. - + The user chooses k by typing k+IS_ALL_CHOICE+1. + if (SYMBOL_CLASS (func) == LOC_CONST + && TYPE_CODE (func_type) == TYPE_CODE_ENUM) + return (n_actuals == 0); + else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC) + return 0; - The user is not allowed to choose more than MAX_RESULTS values. + if (TYPE_NFIELDS (func_type) != n_actuals) + return 0; - ANNOTATION_SUFFIX, if present, is used to annotate the input - prompts (for use with the -f switch). */ + for (i = 0; i < n_actuals; i += 1) + { + if (actuals[i] == NULL) + return 0; + else + { + struct type *ftype = ada_check_typedef (TYPE_FIELD_TYPE (func_type, + i)); + struct type *atype = ada_check_typedef (value_type (actuals[i])); -int -get_selections (int *choices, int n_choices, int max_results, - int is_all_choice, const char *annotation_suffix) -{ - char *args; - const char *prompt; - int n_chosen; - int first_choice = is_all_choice ? 2 : 1; + if (!ada_type_match (ftype, atype, 1)) + return 0; + } + } + return 1; +} - prompt = getenv ("PS2"); - if (prompt == NULL) - prompt = "> "; +/* False iff function type FUNC_TYPE definitely does not produce a value + compatible with type CONTEXT_TYPE. Conservatively returns 1 if + FUNC_TYPE is not a valid function type with a non-null return type + or an enumerated type. A null CONTEXT_TYPE indicates any non-void type. */ - args = command_line_input (prompt, annotation_suffix); +static int +return_match (struct type *func_type, struct type *context_type) +{ + struct type *return_type; - if (args == NULL) - error_no_arg (_("one or more choice numbers")); + if (func_type == NULL) + return 1; - n_chosen = 0; + if (TYPE_CODE (func_type) == TYPE_CODE_FUNC) + return_type = get_base_type (TYPE_TARGET_TYPE (func_type)); + else + return_type = get_base_type (func_type); + if (return_type == NULL) + return 1; - /* Set choices[0 .. n_chosen-1] to the users' choices in ascending - order, as given in args. Choices are validated. */ - while (1) - { - char *args2; - int choice, j; + context_type = get_base_type (context_type); - args = skip_spaces (args); - if (*args == '\0' && n_chosen == 0) - error_no_arg (_("one or more choice numbers")); - else if (*args == '\0') - break; + if (TYPE_CODE (return_type) == TYPE_CODE_ENUM) + return context_type == NULL || return_type == context_type; + else if (context_type == NULL) + return TYPE_CODE (return_type) != TYPE_CODE_VOID; + else + return TYPE_CODE (return_type) == TYPE_CODE (context_type); +} - choice = strtol (args, &args2, 10); - if (args == args2 || choice < 0 - || choice > n_choices + first_choice - 1) - error (_("Argument must be choice number")); - args = args2; - if (choice == 0) - error (_("cancelled")); +/* Returns the index in SYMS[0..NSYMS-1] that contains the symbol for the + function (if any) that matches the types of the NARGS arguments in + ARGS. If CONTEXT_TYPE is non-null and there is at least one match + that returns that type, then eliminate matches that don't. If + CONTEXT_TYPE is void and there is at least one match that does not + return void, eliminate all matches that do. - if (choice < first_choice) - { - n_chosen = n_choices; - for (j = 0; j < n_choices; j += 1) - choices[j] = j; - break; - } - choice -= first_choice; + Asks the user if there is more than one match remaining. Returns -1 + if there is no such symbol or none is selected. NAME is used + solely for messages. May re-arrange and modify SYMS in + the process; the index returned is for the modified vector. */ - for (j = n_chosen - 1; j >= 0 && choice < choices[j]; j -= 1) - { - } +static int +ada_resolve_function (struct block_symbol syms[], + int nsyms, struct value **args, int nargs, + const char *name, struct type *context_type, + int parse_completion) +{ + int fallback; + int k; + int m; /* Number of hits */ - if (j < 0 || choice != choices[j]) + m = 0; + /* In the first pass of the loop, we only accept functions matching + context_type. If none are found, we add a second pass of the loop + where every function is accepted. */ + for (fallback = 0; m == 0 && fallback < 2; fallback++) + { + for (k = 0; k < nsyms; k += 1) { - int k; + struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol)); - for (k = n_chosen - 1; k > j; k -= 1) - choices[k + 1] = choices[k]; - choices[j + 1] = choice; - n_chosen += 1; + if (ada_args_match (syms[k].symbol, args, nargs) + && (fallback || return_match (type, context_type))) + { + syms[m] = syms[k]; + m += 1; + } } } - if (n_chosen > max_results) - error (_("Select no more than %d of the above"), max_results); - - return n_chosen; + /* If we got multiple matches, ask the user which one to use. Don't do this + interactive thing during completion, though, as the purpose of the + completion is providing a list of all possible matches. Prompting the + user to filter it down would be completely unexpected in this case. */ + if (m == 0) + return -1; + else if (m > 1 && !parse_completion) + { + printf_filtered (_("Multiple matches for %s\n"), name); + user_select_syms (syms, m, 1); + return 0; + } + return 0; } /* Replace the operator of length OPLEN at position PC in *EXPP with a call @@ -4284,57 +4290,182 @@ ada_parse_renaming (struct symbol *sym, } } - if (renamed_entity != NULL) - *renamed_entity = info; - suffix = strstr (info, "___XE"); - if (suffix == NULL || suffix == info) - return ADA_NOT_RENAMING; - if (len != NULL) - *len = strlen (info) - strlen (suffix); - suffix += 5; - if (renaming_expr != NULL) - *renaming_expr = suffix; - return kind; -} + if (renamed_entity != NULL) + *renamed_entity = info; + suffix = strstr (info, "___XE"); + if (suffix == NULL || suffix == info) + return ADA_NOT_RENAMING; + if (len != NULL) + *len = strlen (info) - strlen (suffix); + suffix += 5; + if (renaming_expr != NULL) + *renaming_expr = suffix; + return kind; +} + +/* Compute the value of the given RENAMING_SYM, which is expected to + be a symbol encoding a renaming expression. BLOCK is the block + used to evaluate the renaming. */ + +static struct value * +ada_read_renaming_var_value (struct symbol *renaming_sym, + const struct block *block) +{ + const char *sym_name; + + sym_name = SYMBOL_LINKAGE_NAME (renaming_sym); + expression_up expr = parse_exp_1 (&sym_name, 0, block, 0); + return evaluate_expression (expr.get ()); +} + + + /* Evaluation: Function Calls */ + +/* Return an lvalue containing the value VAL. This is the identity on + lvalues, and otherwise has the side-effect of allocating memory + in the inferior where a copy of the value contents is copied. */ + +static struct value * +ensure_lval (struct value *val) +{ + if (VALUE_LVAL (val) == not_lval + || VALUE_LVAL (val) == lval_internalvar) + { + int len = TYPE_LENGTH (ada_check_typedef (value_type (val))); + const CORE_ADDR addr = + value_as_long (value_allocate_space_in_inferior (len)); + + VALUE_LVAL (val) = lval_memory; + set_value_address (val, addr); + write_memory (addr, value_contents (val), len); + } + + return val; +} + +/* Given ARG, a value of type (pointer or reference to a)* + structure/union, extract the component named NAME from the ultimate + target structure/union and return it as a value with its + appropriate type. + + The routine searches for NAME among all members of the structure itself + and (recursively) among all members of any wrapper members + (e.g., '_parent'). + + If NO_ERR, then simply return NULL in case of error, rather than + calling error. */ + +static struct value * +ada_value_struct_elt (struct value *arg, const char *name, int no_err) +{ + struct type *t, *t1; + struct value *v; + int check_tag; + + v = NULL; + t1 = t = ada_check_typedef (value_type (arg)); + if (TYPE_CODE (t) == TYPE_CODE_REF) + { + t1 = TYPE_TARGET_TYPE (t); + if (t1 == NULL) + goto BadValue; + t1 = ada_check_typedef (t1); + if (TYPE_CODE (t1) == TYPE_CODE_PTR) + { + arg = coerce_ref (arg); + t = t1; + } + } + + while (TYPE_CODE (t) == TYPE_CODE_PTR) + { + t1 = TYPE_TARGET_TYPE (t); + if (t1 == NULL) + goto BadValue; + t1 = ada_check_typedef (t1); + if (TYPE_CODE (t1) == TYPE_CODE_PTR) + { + arg = value_ind (arg); + t = t1; + } + else + break; + } -/* Compute the value of the given RENAMING_SYM, which is expected to - be a symbol encoding a renaming expression. BLOCK is the block - used to evaluate the renaming. */ + if (TYPE_CODE (t1) != TYPE_CODE_STRUCT && TYPE_CODE (t1) != TYPE_CODE_UNION) + goto BadValue; -static struct value * -ada_read_renaming_var_value (struct symbol *renaming_sym, - const struct block *block) -{ - const char *sym_name; + if (t1 == t) + v = ada_search_struct_field (name, arg, 0, t); + else + { + int bit_offset, bit_size, byte_offset; + struct type *field_type; + CORE_ADDR address; - sym_name = SYMBOL_LINKAGE_NAME (renaming_sym); - expression_up expr = parse_exp_1 (&sym_name, 0, block, 0); - return evaluate_expression (expr.get ()); -} - + if (TYPE_CODE (t) == TYPE_CODE_PTR) + address = value_address (ada_value_ind (arg)); + else + address = value_address (ada_coerce_ref (arg)); - /* Evaluation: Function Calls */ + /* Check to see if this is a tagged type. We also need to handle + the case where the type is a reference to a tagged type, but + we have to be careful to exclude pointers to tagged types. + The latter should be shown as usual (as a pointer), whereas + a reference should mostly be transparent to the user. */ -/* Return an lvalue containing the value VAL. This is the identity on - lvalues, and otherwise has the side-effect of allocating memory - in the inferior where a copy of the value contents is copied. */ + if (ada_is_tagged_type (t1, 0) + || (TYPE_CODE (t1) == TYPE_CODE_REF + && ada_is_tagged_type (TYPE_TARGET_TYPE (t1), 0))) + { + /* We first try to find the searched field in the current type. + If not found then let's look in the fixed type. */ -static struct value * -ensure_lval (struct value *val) -{ - if (VALUE_LVAL (val) == not_lval - || VALUE_LVAL (val) == lval_internalvar) - { - int len = TYPE_LENGTH (ada_check_typedef (value_type (val))); - const CORE_ADDR addr = - value_as_long (value_allocate_space_in_inferior (len)); + if (!find_struct_field (name, t1, 0, + &field_type, &byte_offset, &bit_offset, + &bit_size, NULL)) + check_tag = 1; + else + check_tag = 0; + } + else + check_tag = 0; - VALUE_LVAL (val) = lval_memory; - set_value_address (val, addr); - write_memory (addr, value_contents (val), len); + /* Convert to fixed type in all cases, so that we have proper + offsets to each field in unconstrained record types. */ + t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, + address, NULL, check_tag); + + if (find_struct_field (name, t1, 0, + &field_type, &byte_offset, &bit_offset, + &bit_size, NULL)) + { + if (bit_size != 0) + { + if (TYPE_CODE (t) == TYPE_CODE_REF) + arg = ada_coerce_ref (arg); + else + arg = ada_value_ind (arg); + v = ada_value_primitive_packed_val (arg, NULL, byte_offset, + bit_offset, bit_size, + field_type); + } + else + v = value_at_lazy (field_type, address + byte_offset); + } } - return val; + if (v != NULL || no_err) + return v; + else + error (_("There is no member named %s."), name); + + BadValue: + if (no_err) + return NULL; + else + error (_("Attempt to extract a component of " + "a value that is not a record.")); } /* Return the value ACTUAL, converted to be an appropriate value for a @@ -6491,7 +6622,7 @@ ada_is_tag_type (struct type *type) /* The type of the tag on VAL. */ -struct type * +static struct type * ada_tag_type (struct value *val) { return ada_lookup_struct_elt_type (value_type (val), "_tag", 1, 0); @@ -6508,7 +6639,7 @@ is_ada95_tag (struct value *tag) /* The value of the tag on VAL. */ -struct value * +static struct value * ada_value_tag (struct value *val) { return ada_value_struct_elt (val, "_tag", 0); @@ -6860,7 +6991,7 @@ ada_variant_discrim_type (struct type *var_type, struct type *outer_type) valid field number within it, returns 1 iff field FIELD_NUM of TYPE represents a 'when others' clause; otherwise 0. */ -int +static int ada_is_others_clause (struct type *type, int field_num) { const char *name = TYPE_FIELD_NAME (type, field_num); @@ -6968,7 +7099,7 @@ ada_scan_number (const char str[], int k, LONGEST * R, int *new_k) and FIELD_NUM is a valid field number within it, returns 1 iff VAL is in the range encoded by field FIELD_NUM of TYPE; otherwise 0. */ -int +static int ada_in_variant (LONGEST val, struct type *type, int field_num) { const char *name = TYPE_FIELD_NAME (type, field_num); @@ -7369,131 +7500,6 @@ ada_index_struct_field_1 (int *index_p, struct value *arg, int offset, return NULL; } -/* Given ARG, a value of type (pointer or reference to a)* - structure/union, extract the component named NAME from the ultimate - target structure/union and return it as a value with its - appropriate type. - - The routine searches for NAME among all members of the structure itself - and (recursively) among all members of any wrapper members - (e.g., '_parent'). - - If NO_ERR, then simply return NULL in case of error, rather than - calling error. */ - -struct value * -ada_value_struct_elt (struct value *arg, const char *name, int no_err) -{ - struct type *t, *t1; - struct value *v; - int check_tag; - - v = NULL; - t1 = t = ada_check_typedef (value_type (arg)); - if (TYPE_CODE (t) == TYPE_CODE_REF) - { - t1 = TYPE_TARGET_TYPE (t); - if (t1 == NULL) - goto BadValue; - t1 = ada_check_typedef (t1); - if (TYPE_CODE (t1) == TYPE_CODE_PTR) - { - arg = coerce_ref (arg); - t = t1; - } - } - - while (TYPE_CODE (t) == TYPE_CODE_PTR) - { - t1 = TYPE_TARGET_TYPE (t); - if (t1 == NULL) - goto BadValue; - t1 = ada_check_typedef (t1); - if (TYPE_CODE (t1) == TYPE_CODE_PTR) - { - arg = value_ind (arg); - t = t1; - } - else - break; - } - - if (TYPE_CODE (t1) != TYPE_CODE_STRUCT && TYPE_CODE (t1) != TYPE_CODE_UNION) - goto BadValue; - - if (t1 == t) - v = ada_search_struct_field (name, arg, 0, t); - else - { - int bit_offset, bit_size, byte_offset; - struct type *field_type; - CORE_ADDR address; - - if (TYPE_CODE (t) == TYPE_CODE_PTR) - address = value_address (ada_value_ind (arg)); - else - address = value_address (ada_coerce_ref (arg)); - - /* Check to see if this is a tagged type. We also need to handle - the case where the type is a reference to a tagged type, but - we have to be careful to exclude pointers to tagged types. - The latter should be shown as usual (as a pointer), whereas - a reference should mostly be transparent to the user. */ - - if (ada_is_tagged_type (t1, 0) - || (TYPE_CODE (t1) == TYPE_CODE_REF - && ada_is_tagged_type (TYPE_TARGET_TYPE (t1), 0))) - { - /* We first try to find the searched field in the current type. - If not found then let's look in the fixed type. */ - - if (!find_struct_field (name, t1, 0, - &field_type, &byte_offset, &bit_offset, - &bit_size, NULL)) - check_tag = 1; - else - check_tag = 0; - } - else - check_tag = 0; - - /* Convert to fixed type in all cases, so that we have proper - offsets to each field in unconstrained record types. */ - t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, - address, NULL, check_tag); - - if (find_struct_field (name, t1, 0, - &field_type, &byte_offset, &bit_offset, - &bit_size, NULL)) - { - if (bit_size != 0) - { - if (TYPE_CODE (t) == TYPE_CODE_REF) - arg = ada_coerce_ref (arg); - else - arg = ada_value_ind (arg); - v = ada_value_primitive_packed_val (arg, NULL, byte_offset, - bit_offset, bit_size, - field_type); - } - else - v = value_at_lazy (field_type, address + byte_offset); - } - } - - if (v != NULL || no_err) - return v; - else - error (_("There is no member named %s."), name); - - BadValue: - if (no_err) - return NULL; - else - error (_("Attempt to extract a component of " - "a value that is not a record.")); -} - /* Return a string representation of type TYPE. */ static std::string @@ -9145,7 +9151,7 @@ static const char *attribute_names[] = { 0 }; -const char * +static const char * ada_attribute_name (enum exp_opcode n) { if (n >= OP_ATR_FIRST && n <= (int) OP_ATR_VAL) diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h index b68dd4e97d0..13a917affec 100644 --- a/gdb/ada-lang.h +++ b/gdb/ada-lang.h @@ -149,14 +149,6 @@ struct ada_task_info int base_cpu; }; -/* Assuming V points to an array of S objects, make sure that it contains at - least M objects, updating V and S as necessary. */ - -#define GROW_VECT(v, s, m) \ - if ((s) < (m)) (v) = (char *) grow_vect (v, &(s), m, sizeof *(v)); - -extern void *grow_vect (void *, size_t *, size_t, int); - extern void ada_ensure_varsize_limit (const struct type *type); extern int ada_get_field_index (const struct type *type, @@ -204,8 +196,6 @@ extern struct type *ada_array_element_type (struct type *, int); extern int ada_array_arity (struct type *); -struct type *ada_type_of_array (struct value *, int); - extern struct value *ada_coerce_to_simple_array_ptr (struct value *); struct value *ada_coerce_to_simple_array (struct value *); @@ -228,14 +218,10 @@ extern const char *ada_decode_symbol (const struct general_symbol_info *); extern std::string ada_decode (const char*); -extern enum language ada_update_initial_language (enum language); - extern int ada_lookup_symbol_list (const char *, const struct block *, domain_enum, std::vector *); -extern char *ada_fold_name (const char *); - extern struct block_symbol ada_lookup_symbol (const char *, const struct block *, domain_enum); @@ -246,12 +232,6 @@ extern void ada_lookup_encoded_symbol extern struct bound_minimal_symbol ada_lookup_simple_minsym (const char *); -extern void ada_fill_in_ada_prototype (struct symbol *); - -extern int user_select_syms (struct block_symbol *, int, int); - -extern int get_selections (int *, int, int, int, const char *); - extern int ada_scan_number (const char *, int, LONGEST *, int *); extern struct type *ada_parent_type (struct type *); @@ -275,10 +255,6 @@ extern int ada_is_tagged_type (struct type *, int); extern int ada_is_tag_type (struct type *); -extern struct type *ada_tag_type (struct value *); - -extern struct value *ada_value_tag (struct value *); - extern const char *ada_tag_name (struct value *); extern struct value *ada_tag_value_at_base_address (struct value *obj); @@ -291,14 +267,8 @@ extern int ada_is_variant_part (struct type *, int); extern struct type *ada_variant_discrim_type (struct type *, struct type *); -extern int ada_is_others_clause (struct type *, int); - -extern int ada_in_variant (LONGEST, struct type *, int); - extern const char *ada_variant_discrim_name (struct type *); -extern struct value *ada_value_struct_elt (struct value *, const char *, int); - extern int ada_is_aligner_type (struct type *); extern struct type *ada_aligned_type (struct type *); @@ -306,8 +276,6 @@ extern struct type *ada_aligned_type (struct type *); extern const gdb_byte *ada_aligned_value_addr (struct type *, const gdb_byte *); -extern const char *ada_attribute_name (enum exp_opcode); - extern int ada_is_fixed_point_type (struct type *); extern int ada_is_system_address_type (struct type *); @@ -316,8 +284,6 @@ extern struct value *ada_delta (struct type *); extern struct value *ada_scaling_factor (struct type *); -extern struct type *ada_system_address_type (void); - extern int ada_which_variant_applies (struct type *, struct type *, const gdb_byte *); -- 2.30.2