X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=3403a857a8396190b039dd2ae595e258f3c96990;hb=f1f28025c3ea75d5368ddd3046461648145b89b3;hp=8f0aa00f5296c3d7d9be0031e698494ed5ad41e4;hpb=59498c305e6f1db2a1ed8d44cb58f0d24ec092fe;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 8f0aa00f52..3403a857a8 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -1,5 +1,5 @@ /* YACC parser for C expressions, for GDB. - Copyright (C) 1986-2018 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -42,6 +42,7 @@ #include "parser-defs.h" #include "language.h" #include "c-lang.h" +#include "c-support.h" #include "bfd.h" /* Required by objfiles.h. */ #include "symfile.h" /* Required by objfiles.h. */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ @@ -52,8 +53,9 @@ #include "objc-lang.h" #include "typeprint.h" #include "cp-abi.h" +#include "type-stack.h" -#define parse_type(ps) builtin_type (parse_gdbarch (ps)) +#define parse_type(ps) builtin_type (ps->gdbarch ()) /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc). */ @@ -65,11 +67,58 @@ static struct parser_state *pstate = NULL; +/* Data that must be held for the duration of a parse. */ + +struct c_parse_state +{ + /* These are used to hold type lists and type stacks that are + allocated during the parse. */ + std::vector>> type_lists; + std::vector> type_stacks; + + /* Storage for some strings allocated during the parse. */ + std::vector> strings; + + /* When we find that lexptr (the global var defined in parse.c) is + pointing at a macro invocation, we expand the invocation, and call + scan_macro_expansion to save the old lexptr here and point lexptr + into the expanded text. When we reach the end of that, we call + end_macro_expansion to pop back to the value we saved here. The + macro expansion code promises to return only fully-expanded text, + so we don't need to "push" more than one level. + + This is disgusting, of course. It would be cleaner to do all macro + expansion beforehand, and then hand that to lexptr. But we don't + really know where the expression ends. Remember, in a command like + + (gdb) break *ADDRESS if CONDITION + + we evaluate ADDRESS in the scope of the current frame, but we + evaluate CONDITION in the scope of the breakpoint's location. So + it's simply wrong to try to macro-expand the whole thing at once. */ + const char *macro_original_text = nullptr; + + /* We save all intermediate macro expansions on this obstack for the + duration of a single parse. The expansion text may sometimes have + to live past the end of the expansion, due to yacc lookahead. + Rather than try to be clever about saving the data for a single + token, we simply keep it all and delete it after parsing has + completed. */ + auto_obstack expansion_obstack; + + /* The type stack. */ + struct type_stack type_stack; +}; + +/* This is set and cleared in c_parse. */ + +static struct c_parse_state *cpstate; + int yyparse (void); static int yylex (void); -void yyerror (const char *); +static void yyerror (const char *); static int type_aggregate_p (struct type *); @@ -100,7 +149,7 @@ static int type_aggregate_p (struct type *); enum exp_opcode opcode; struct stoken_vector svec; - VEC (type_ptr) *tvec; + std::vector *tvec; struct type_stack *type_stack; @@ -112,7 +161,8 @@ static int type_aggregate_p (struct type *); static int parse_number (struct parser_state *par_state, const char *, int, int, YYSTYPE *); static struct stoken operator_stoken (const char *); -static void check_parameter_typelist (VEC (type_ptr) *); +static struct stoken typename_stoken (const char *); +static void check_parameter_typelist (std::vector *); static void write_destructor_name (struct parser_state *par_state, struct stoken); @@ -155,7 +205,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %token COMPLETE %token TYPENAME %token CLASSNAME /* ObjC Class name */ -%type name +%type name field_name %type string_exp %type name_not_typename %type type_name @@ -173,7 +223,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %token NAME_OR_INT %token OPERATOR -%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON +%token STRUCT CLASS UNION ENUM SIZEOF ALIGNOF UNSIGNED COLONCOLON %token TEMPLATE %token ERROR %token NEW DELETE @@ -188,7 +238,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); legal basetypes. */ %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD -%token VARIABLE +%token DOLLAR_VARIABLE %token ASSIGN_MODIFY @@ -307,14 +357,18 @@ exp : SIZEOF exp %prec UNARY { write_exp_elt_opcode (pstate, UNOP_SIZEOF); } ; -exp : exp ARROW name +exp : ALIGNOF '(' type_exp ')' %prec UNARY + { write_exp_elt_opcode (pstate, UNOP_ALIGNOF); } + ; + +exp : exp ARROW field_name { write_exp_elt_opcode (pstate, STRUCTOP_PTR); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_PTR); } ; -exp : exp ARROW name COMPLETE - { mark_struct_expression (pstate); +exp : exp ARROW field_name COMPLETE + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_PTR); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_PTR); } @@ -322,7 +376,7 @@ exp : exp ARROW name COMPLETE exp : exp ARROW COMPLETE { struct stoken s; - mark_struct_expression (pstate); + pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_PTR); s.ptr = ""; s.length = 0; @@ -337,7 +391,7 @@ exp : exp ARROW '~' name ; exp : exp ARROW '~' name COMPLETE - { mark_struct_expression (pstate); + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_PTR); write_destructor_name (pstate, $4); write_exp_elt_opcode (pstate, STRUCTOP_PTR); } @@ -355,14 +409,14 @@ exp : exp ARROW_STAR exp { write_exp_elt_opcode (pstate, STRUCTOP_MPTR); } ; -exp : exp '.' name +exp : exp '.' field_name { write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } ; -exp : exp '.' name COMPLETE - { mark_struct_expression (pstate); +exp : exp '.' field_name COMPLETE + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } @@ -370,7 +424,7 @@ exp : exp '.' name COMPLETE exp : exp '.' COMPLETE { struct stoken s; - mark_struct_expression (pstate); + pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); s.ptr = ""; s.length = 0; @@ -385,7 +439,7 @@ exp : exp '.' '~' name ; exp : exp '.' '~' name COMPLETE - { mark_struct_expression (pstate); + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); write_destructor_name (pstate, $4); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } @@ -420,14 +474,15 @@ exp : OBJC_LBRAC TYPENAME { CORE_ADDR theclass; - theclass = lookup_objc_class (parse_gdbarch (pstate), - copy_name ($2.stoken)); + std::string copy = copy_name ($2.stoken); + theclass = lookup_objc_class (pstate->gdbarch (), + copy.c_str ()); if (theclass == 0) error (_("%s is not an ObjC Class"), - copy_name ($2.stoken)); + copy.c_str ()); write_exp_elt_opcode (pstate, OP_LONG); write_exp_elt_type (pstate, - parse_type (pstate)->builtin_int); + parse_type (pstate)->builtin_int); write_exp_elt_longcst (pstate, (LONGEST) theclass); write_exp_elt_opcode (pstate, OP_LONG); start_msglist(); @@ -484,11 +539,11 @@ msgarg : name ':' exp exp : exp '(' /* This is to save the value of arglist_len being accumulated by an outer function call. */ - { start_arglist (); } + { pstate->start_arglist (); } arglist ')' %prec ARROW { write_exp_elt_opcode (pstate, OP_FUNCALL); write_exp_elt_longcst (pstate, - (LONGEST) end_arglist ()); + pstate->end_arglist ()); write_exp_elt_opcode (pstate, OP_FUNCALL); } ; @@ -496,10 +551,10 @@ exp : exp '(' "func()::static_var" further below, which uses function_method_void. */ exp : exp '(' ')' %prec ARROW - { start_arglist (); + { pstate->start_arglist (); write_exp_elt_opcode (pstate, OP_FUNCALL); write_exp_elt_longcst (pstate, - (LONGEST) end_arglist ()); + pstate->end_arglist ()); write_exp_elt_opcode (pstate, OP_FUNCALL); } ; @@ -509,8 +564,8 @@ exp : UNKNOWN_CPP_NAME '(' /* This could potentially be a an argument defined lookup function (Koenig). */ write_exp_elt_opcode (pstate, OP_ADL_FUNC); - write_exp_elt_block (pstate, - expression_context_block); + write_exp_elt_block + (pstate, pstate->expression_context_block); write_exp_elt_sym (pstate, NULL); /* Placeholder. */ write_exp_string (pstate, $1.stoken); @@ -519,60 +574,59 @@ exp : UNKNOWN_CPP_NAME '(' /* This is to save the value of arglist_len being accumulated by an outer function call. */ - start_arglist (); + pstate->start_arglist (); } arglist ')' %prec ARROW { write_exp_elt_opcode (pstate, OP_FUNCALL); write_exp_elt_longcst (pstate, - (LONGEST) end_arglist ()); + pstate->end_arglist ()); write_exp_elt_opcode (pstate, OP_FUNCALL); } ; lcurly : '{' - { start_arglist (); } + { pstate->start_arglist (); } ; arglist : ; arglist : exp - { arglist_len = 1; } + { pstate->arglist_len = 1; } ; arglist : arglist ',' exp %prec ABOVE_COMMA - { arglist_len++; } + { pstate->arglist_len++; } ; function_method: exp '(' parameter_typelist ')' const_or_volatile - { int i; - VEC (type_ptr) *type_list = $3; - struct type *type_elt; - LONGEST len = VEC_length (type_ptr, type_list); + { + std::vector *type_list = $3; + LONGEST len = type_list->size (); write_exp_elt_opcode (pstate, TYPE_INSTANCE); /* Save the const/volatile qualifiers as recorded by the const_or_volatile production's actions. */ - write_exp_elt_longcst (pstate, - follow_type_instance_flags ()); + write_exp_elt_longcst + (pstate, + (cpstate->type_stack + .follow_type_instance_flags ())); write_exp_elt_longcst (pstate, len); - for (i = 0; - VEC_iterate (type_ptr, type_list, i, type_elt); - ++i) + for (type *type_elt : *type_list) write_exp_elt_type (pstate, type_elt); write_exp_elt_longcst(pstate, len); write_exp_elt_opcode (pstate, TYPE_INSTANCE); - VEC_free (type_ptr, type_list); } ; function_method_void: exp '(' ')' const_or_volatile { write_exp_elt_opcode (pstate, TYPE_INSTANCE); /* See above. */ - write_exp_elt_longcst (pstate, - follow_type_instance_flags ()); + write_exp_elt_longcst + (pstate, + cpstate->type_stack.follow_type_instance_flags ()); write_exp_elt_longcst (pstate, 0); write_exp_elt_longcst (pstate, 0); write_exp_elt_opcode (pstate, TYPE_INSTANCE); @@ -599,7 +653,7 @@ exp : function_method_void_or_typelist COLONCOLON name ; rcurly : '}' - { $$ = end_arglist () - 1; } + { $$ = pstate->end_arglist () - 1; } ; exp : lcurly arglist rcurly %prec ARROW { write_exp_elt_opcode (pstate, OP_ARRAY); @@ -752,7 +806,7 @@ exp : FLOAT exp : variable ; -exp : VARIABLE +exp : DOLLAR_VARIABLE { write_dollar_variable (pstate, $1); } @@ -769,8 +823,7 @@ exp : SIZEOF '(' type ')' %prec UNARY { struct type *type = $3; write_exp_elt_opcode (pstate, OP_LONG); write_exp_elt_type (pstate, lookup_signed_typename - (parse_language (pstate), - parse_gdbarch (pstate), + (pstate->language (), "int")); type = check_typedef (type); @@ -906,7 +959,7 @@ block : BLOCKNAME $$ = SYMBOL_BLOCK_VALUE ($1.sym.symbol); else error (_("No file or function \"%s\"."), - copy_name ($1.stoken)); + copy_name ($1.stoken).c_str ()); } | FILENAME { @@ -915,13 +968,15 @@ block : BLOCKNAME ; block : block COLONCOLON name - { struct symbol *tem - = lookup_symbol (copy_name ($3), $1, + { + std::string copy = copy_name ($3); + struct symbol *tem + = lookup_symbol (copy.c_str (), $1, VAR_DOMAIN, NULL).symbol; if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) error (_("No function \"%s\" in specified context."), - copy_name ($3)); + copy.c_str ()); $$ = SYMBOL_BLOCK_VALUE (tem); } ; @@ -932,7 +987,7 @@ variable: name_not_typename ENTRY || !symbol_read_needs_frame (sym)) error (_("@entry can be used only for function " "parameters, not for \"%s\""), - copy_name ($1.stoken)); + copy_name ($1.stoken).c_str ()); write_exp_elt_opcode (pstate, OP_VAR_ENTRY_VALUE); write_exp_elt_sym (pstate, sym); @@ -941,16 +996,17 @@ variable: name_not_typename ENTRY ; variable: block COLONCOLON name - { struct block_symbol sym - = lookup_symbol (copy_name ($3), $1, + { + std::string copy = copy_name ($3); + struct block_symbol sym + = lookup_symbol (copy.c_str (), $1, VAR_DOMAIN, NULL); if (sym.symbol == 0) error (_("No symbol \"%s\" in specified context."), - copy_name ($3)); + copy.c_str ()); if (symbol_read_needs_frame (sym.symbol)) - - innermost_block.update (sym); + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); @@ -997,22 +1053,23 @@ qualified_name: TYPENAME COLONCOLON name } | TYPENAME COLONCOLON name COLONCOLON name { - char *copy = copy_name ($3); + std::string copy = copy_name ($3); error (_("No type \"%s\" within class " "or namespace \"%s\"."), - copy, TYPE_SAFE_NAME ($1.type)); + copy.c_str (), TYPE_SAFE_NAME ($1.type)); } ; variable: qualified_name | COLONCOLON name_not_typename { - char *name = copy_name ($2.stoken); + std::string name = copy_name ($2.stoken); struct symbol *sym; struct bound_minimal_symbol msymbol; sym - = lookup_symbol (name, (const struct block *) NULL, + = lookup_symbol (name.c_str (), + (const struct block *) NULL, VAR_DOMAIN, NULL).symbol; if (sym) { @@ -1023,13 +1080,14 @@ variable: qualified_name break; } - msymbol = lookup_bound_minimal_symbol (name); + msymbol = lookup_bound_minimal_symbol (name.c_str ()); if (msymbol.minsym != NULL) write_exp_msymbol (pstate, msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); else - error (_("No symbol \"%s\" in current context."), name); + error (_("No symbol \"%s\" in current context."), + name.c_str ()); } ; @@ -1039,19 +1097,31 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) - innermost_block.update (sym); + pstate->block_tracker->update (sym); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, sym.block); - write_exp_elt_sym (pstate, sym.symbol); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); + /* If we found a function, see if it's + an ifunc resolver that has the same + address as the ifunc symbol itself. + If so, prefer the ifunc symbol. */ + + bound_minimal_symbol resolver + = find_gnu_ifunc (sym.symbol); + if (resolver.minsym != NULL) + write_exp_msymbol (pstate, resolver); + else + { + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + write_exp_elt_block (pstate, sym.block); + write_exp_elt_sym (pstate, sym.symbol); + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + } } else if ($1.is_a_field_of_this) { /* C++: it hangs off of `this'. Must not inadvertently convert from a method call to data ref. */ - innermost_block.update (sym); + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, STRUCTOP_PTR); @@ -1060,17 +1130,17 @@ variable: name_not_typename } else { - char *arg = copy_name ($1.stoken); + std::string arg = copy_name ($1.stoken); bound_minimal_symbol msymbol - = lookup_bound_minimal_symbol (arg); + = lookup_bound_minimal_symbol (arg.c_str ()); if (msymbol.minsym == NULL) { if (!have_full_symbols () && !have_partial_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); else error (_("No symbol \"%s\" in current context."), - copy_name ($1.stoken)); + arg.c_str ()); } /* This minsym might be an alias for @@ -1081,7 +1151,10 @@ variable: name_not_typename is important for example for "p *__errno_location()". */ symbol *alias_target - = find_function_alias_target (msymbol); + = ((msymbol.minsym->type != mst_text_gnu_ifunc + && msymbol.minsym->type != mst_data_gnu_ifunc) + ? find_function_alias_target (msymbol) + : NULL); if (alias_target != NULL) { write_exp_elt_opcode (pstate, OP_VAR_VALUE); @@ -1097,7 +1170,10 @@ variable: name_not_typename ; space_identifier : '@' NAME - { insert_type_address_space (pstate, copy_name ($2.stoken)); } + { + cpstate->type_stack.insert (pstate, + copy_name ($2.stoken).c_str ()); + } ; const_or_volatile: const_or_volatile_noopt @@ -1118,32 +1194,30 @@ const_or_volatile_or_space_identifier: ptr_operator: ptr_operator '*' - { insert_type (tp_pointer); } + { cpstate->type_stack.insert (tp_pointer); } const_or_volatile_or_space_identifier | '*' - { insert_type (tp_pointer); } + { cpstate->type_stack.insert (tp_pointer); } const_or_volatile_or_space_identifier | '&' - { insert_type (tp_reference); } + { cpstate->type_stack.insert (tp_reference); } | '&' ptr_operator - { insert_type (tp_reference); } + { cpstate->type_stack.insert (tp_reference); } | ANDAND - { insert_type (tp_rvalue_reference); } + { cpstate->type_stack.insert (tp_rvalue_reference); } | ANDAND ptr_operator - { insert_type (tp_rvalue_reference); } + { cpstate->type_stack.insert (tp_rvalue_reference); } ; ptr_operator_ts: ptr_operator { - $$ = get_type_stack (); - /* This cleanup is eventually run by - c_parse. */ - make_cleanup (type_stack_cleanup, $$); + $$ = cpstate->type_stack.create (); + cpstate->type_stacks.emplace_back ($$); } ; abs_decl: ptr_operator_ts direct_abs_decl - { $$ = append_type_stack ($2, $1); } + { $$ = $2->append ($1); } | ptr_operator_ts | direct_abs_decl ; @@ -1152,28 +1226,32 @@ direct_abs_decl: '(' abs_decl ')' { $$ = $2; } | direct_abs_decl array_mod { - push_type_stack ($1); - push_type_int ($2); - push_type (tp_array); - $$ = get_type_stack (); + cpstate->type_stack.push ($1); + cpstate->type_stack.push ($2); + cpstate->type_stack.push (tp_array); + $$ = cpstate->type_stack.create (); + cpstate->type_stacks.emplace_back ($$); } | array_mod { - push_type_int ($1); - push_type (tp_array); - $$ = get_type_stack (); + cpstate->type_stack.push ($1); + cpstate->type_stack.push (tp_array); + $$ = cpstate->type_stack.create (); + cpstate->type_stacks.emplace_back ($$); } | direct_abs_decl func_mod { - push_type_stack ($1); - push_typelist ($2); - $$ = get_type_stack (); + cpstate->type_stack.push ($1); + cpstate->type_stack.push ($2); + $$ = cpstate->type_stack.create (); + cpstate->type_stacks.emplace_back ($$); } | func_mod { - push_typelist ($1); - $$ = get_type_stack (); + cpstate->type_stack.push ($1); + $$ = cpstate->type_stack.create (); + cpstate->type_stacks.emplace_back ($$); } ; @@ -1188,7 +1266,10 @@ array_mod: '[' ']' ; func_mod: '(' ')' - { $$ = NULL; } + { + $$ = new std::vector; + cpstate->type_lists.emplace_back ($$); + } | '(' parameter_typelist ')' { $$ = $2; } ; @@ -1204,208 +1285,197 @@ func_mod: '(' ')' type : ptype ; -typebase /* Implements (approximately): (type-qualifier)* type-specifier */ +/* Implements (approximately): (type-qualifier)* type-specifier. + + When type-specifier is only ever a single word, like 'float' then these + arrive as pre-built TYPENAME tokens thanks to the classify_name + function. However, when a type-specifier can contain multiple words, + for example 'double' can appear as just 'double' or 'long double', and + similarly 'long' can appear as just 'long' or in 'long double', then + these type-specifiers are parsed into their own tokens in the function + lex_one_token and the ident_tokens array. These separate tokens are all + recognised here. */ +typebase : TYPENAME { $$ = $1.type; } | INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "int"); } | LONG - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long"); } | SHORT - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "short"); } | LONG INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long"); } | LONG SIGNED_KEYWORD INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long"); } | LONG SIGNED_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long"); } | SIGNED_KEYWORD LONG INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long"); } | UNSIGNED LONG INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long"); } | LONG UNSIGNED INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long"); } | LONG UNSIGNED - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long"); } | LONG LONG - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | LONG LONG INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | LONG LONG SIGNED_KEYWORD INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | LONG LONG SIGNED_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | SIGNED_KEYWORD LONG LONG - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | SIGNED_KEYWORD LONG LONG INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "long long"); } | UNSIGNED LONG LONG - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long long"); } | UNSIGNED LONG LONG INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long long"); } | LONG LONG UNSIGNED - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long long"); } | LONG LONG UNSIGNED INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "long long"); } | SHORT INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "short"); } | SHORT SIGNED_KEYWORD INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "short"); } | SHORT SIGNED_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "short"); } | UNSIGNED SHORT INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "short"); } | SHORT UNSIGNED - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "short"); } | SHORT UNSIGNED INT_KEYWORD - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "short"); } | DOUBLE_KEYWORD - { $$ = lookup_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_typename (pstate->language (), "double", - (struct block *) NULL, + NULL, 0); } | LONG DOUBLE_KEYWORD - { $$ = lookup_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_typename (pstate->language (), "long double", - (struct block *) NULL, + NULL, 0); } | STRUCT name - { $$ = lookup_struct (copy_name ($2), - expression_context_block); } + { $$ + = lookup_struct (copy_name ($2).c_str (), + pstate->expression_context_block); + } | STRUCT COMPLETE { - mark_completion_tag (TYPE_CODE_STRUCT, "", 0); + pstate->mark_completion_tag (TYPE_CODE_STRUCT, + "", 0); $$ = NULL; } | STRUCT name COMPLETE { - mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr, - $2.length); + pstate->mark_completion_tag (TYPE_CODE_STRUCT, + $2.ptr, $2.length); $$ = NULL; } | CLASS name - { $$ = lookup_struct (copy_name ($2), - expression_context_block); } + { $$ = lookup_struct + (copy_name ($2).c_str (), + pstate->expression_context_block); + } | CLASS COMPLETE { - mark_completion_tag (TYPE_CODE_STRUCT, "", 0); + pstate->mark_completion_tag (TYPE_CODE_STRUCT, + "", 0); $$ = NULL; } | CLASS name COMPLETE { - mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr, - $2.length); + pstate->mark_completion_tag (TYPE_CODE_STRUCT, + $2.ptr, $2.length); $$ = NULL; } | UNION name - { $$ = lookup_union (copy_name ($2), - expression_context_block); } + { $$ + = lookup_union (copy_name ($2).c_str (), + pstate->expression_context_block); + } | UNION COMPLETE { - mark_completion_tag (TYPE_CODE_UNION, "", 0); + pstate->mark_completion_tag (TYPE_CODE_UNION, + "", 0); $$ = NULL; } | UNION name COMPLETE { - mark_completion_tag (TYPE_CODE_UNION, $2.ptr, - $2.length); + pstate->mark_completion_tag (TYPE_CODE_UNION, + $2.ptr, $2.length); $$ = NULL; } | ENUM name - { $$ = lookup_enum (copy_name ($2), - expression_context_block); } + { $$ = lookup_enum (copy_name ($2).c_str (), + pstate->expression_context_block); + } | ENUM COMPLETE { - mark_completion_tag (TYPE_CODE_ENUM, "", 0); + pstate->mark_completion_tag (TYPE_CODE_ENUM, "", 0); $$ = NULL; } | ENUM name COMPLETE { - mark_completion_tag (TYPE_CODE_ENUM, $2.ptr, - $2.length); + pstate->mark_completion_tag (TYPE_CODE_ENUM, $2.ptr, + $2.length); $$ = NULL; } | UNSIGNED type_name - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), TYPE_NAME($2.type)); } | UNSIGNED - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_unsigned_typename (pstate->language (), "int"); } | SIGNED_KEYWORD type_name - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), TYPE_NAME($2.type)); } | SIGNED_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_signed_typename (pstate->language (), "int"); } /* It appears that this rule for templates is never reduced; template recognition happens by lookahead in the token processing code in yylex. */ | TEMPLATE name '<' type '>' - { $$ = lookup_template_type(copy_name($2), $4, - expression_context_block); + { $$ = lookup_template_type + (copy_name($2).c_str (), $4, + pstate->expression_context_block); } | const_or_volatile_or_space_identifier_noopt typebase - { $$ = follow_types ($2); } + { $$ = cpstate->type_stack.follow_types ($2); } | typebase const_or_volatile_or_space_identifier_noopt - { $$ = follow_types ($1); } + { $$ = cpstate->type_stack.follow_types ($1); } ; type_name: TYPENAME @@ -1413,24 +1483,21 @@ type_name: TYPENAME { $$.stoken.ptr = "int"; $$.stoken.length = 3; - $$.type = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + $$.type = lookup_signed_typename (pstate->language (), "int"); } | LONG { $$.stoken.ptr = "long"; $$.stoken.length = 4; - $$.type = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + $$.type = lookup_signed_typename (pstate->language (), "long"); } | SHORT { $$.stoken.ptr = "short"; $$.stoken.length = 5; - $$.type = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), + $$.type = lookup_signed_typename (pstate->language (), "short"); } ; @@ -1440,7 +1507,7 @@ parameter_typelist: { check_parameter_typelist ($1); } | nonempty_typelist ',' DOTDOTDOT { - VEC_safe_push (type_ptr, $1, NULL); + $1->push_back (NULL); check_parameter_typelist ($1); $$ = $1; } @@ -1449,13 +1516,16 @@ parameter_typelist: nonempty_typelist : type { - VEC (type_ptr) *typelist = NULL; - VEC_safe_push (type_ptr, typelist, $1); + std::vector *typelist + = new std::vector; + cpstate->type_lists.emplace_back (typelist); + + typelist->push_back ($1); $$ = typelist; } | nonempty_typelist ',' type { - VEC_safe_push (type_ptr, $1, $3); + $1->push_back ($3); $$ = $1; } ; @@ -1463,13 +1533,13 @@ nonempty_typelist ptype : typebase | ptype abs_decl { - push_type_stack ($2); - $$ = follow_types ($1); + cpstate->type_stack.push ($2); + $$ = cpstate->type_stack.follow_types ($1); } ; conversion_type_id: typebase conversion_declarator - { $$ = follow_types ($1); } + { $$ = cpstate->type_stack.follow_types ($1); } ; conversion_declarator: /* Nothing. */ @@ -1481,13 +1551,13 @@ const_and_volatile: CONST_KEYWORD VOLATILE_KEYWORD ; const_or_volatile_noopt: const_and_volatile - { insert_type (tp_const); - insert_type (tp_volatile); + { cpstate->type_stack.insert (tp_const); + cpstate->type_stack.insert (tp_volatile); } | CONST_KEYWORD - { insert_type (tp_const); } + { cpstate->type_stack.insert (tp_const); } | VOLATILE_KEYWORD - { insert_type (tp_volatile); } + { cpstate->type_stack.insert (tp_volatile); } ; oper: OPERATOR NEW @@ -1615,7 +1685,22 @@ oper: OPERATOR NEW } ; - +/* This rule exists in order to allow some tokens that would not normally + match the 'name' rule to appear as fields within a struct. The example + that initially motivated this was the RISC-V target which models the + floating point registers as a union with fields called 'float' and + 'double'. The 'float' string becomes a TYPENAME token and can appear + anywhere a 'name' can, however 'double' is its own token, + DOUBLE_KEYWORD, and doesn't match the 'name' rule.*/ +field_name + : name + | DOUBLE_KEYWORD { $$ = typename_stoken ("double"); } + | INT_KEYWORD { $$ = typename_stoken ("int"); } + | LONG { $$ = typename_stoken ("long"); } + | SHORT { $$ = typename_stoken ("short"); } + | SIGNED_KEYWORD { $$ = typename_stoken ("signed"); } + | UNSIGNED { $$ = typename_stoken ("unsigned"); } + ; name : NAME { $$ = $1.stoken; } | BLOCKNAME { $$ = $1.stoken; } @@ -1639,10 +1724,11 @@ name_not_typename : NAME struct field_of_this_result is_a_field_of_this; $$.stoken = $1; - $$.sym = lookup_symbol ($1.ptr, - expression_context_block, - VAR_DOMAIN, - &is_a_field_of_this); + $$.sym + = lookup_symbol ($1.ptr, + pstate->expression_context_block, + VAR_DOMAIN, + &is_a_field_of_this); $$.is_a_field_of_this = is_a_field_of_this.type != NULL; } @@ -1683,7 +1769,17 @@ operator_stoken (const char *op) st.ptr = buf; /* The toplevel (c_parse) will free the memory allocated here. */ - make_cleanup (free, buf); + cpstate->strings.emplace_back (buf); + return st; +}; + +/* Returns a stoken of the type named TYPE. */ + +static struct stoken +typename_stoken (const char *type) +{ + struct stoken st = { type, 0 }; + st.length = strlen (type); return st; }; @@ -1702,30 +1798,27 @@ type_aggregate_p (struct type *type) /* Validate a parameter typelist. */ static void -check_parameter_typelist (VEC (type_ptr) *params) +check_parameter_typelist (std::vector *params) { struct type *type; int ix; - for (ix = 0; VEC_iterate (type_ptr, params, ix, type); ++ix) + for (ix = 0; ix < params->size (); ++ix) { + type = (*params)[ix]; if (type != NULL && TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) { if (ix == 0) { - if (VEC_length (type_ptr, params) == 1) + if (params->size () == 1) { /* Ok. */ break; } - VEC_free (type_ptr, params); error (_("parameter types following 'void'")); } else - { - VEC_free (type_ptr, params); - error (_("'void' invalid as parameter type")); - } + error (_("'void' invalid as parameter type")); } } } @@ -1740,10 +1833,8 @@ static int parse_number (struct parser_state *par_state, const char *buf, int len, int parsed_float, YYSTYPE *putithere) { - /* FIXME: Shouldn't these be unsigned? We don't deal with negative values - here, and we do kind of silly things like cast to unsigned. */ - LONGEST n = 0; - LONGEST prevn = 0; + ULONGEST n = 0; + ULONGEST prevn = 0; ULONGEST un; int i = 0; @@ -1787,13 +1878,13 @@ parse_number (struct parser_state *par_state, len -= 2; } /* Handle suffixes: 'f' for float, 'l' for long double. */ - else if (len >= 1 && tolower (p[len - 1]) == 'f') + else if (len >= 1 && TOLOWER (p[len - 1]) == 'f') { putithere->typed_val_float.type = parse_type (par_state)->builtin_float; len -= 1; } - else if (len >= 1 && tolower (p[len - 1]) == 'l') + else if (len >= 1 && TOLOWER (p[len - 1]) == 'l') { putithere->typed_val_float.type = parse_type (par_state)->builtin_long_double; @@ -1902,7 +1993,7 @@ parse_number (struct parser_state *par_state, on 0x123456789 when LONGEST is 32 bits. */ if (c != 'l' && c != 'u' && n != 0) { - if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n)) + if (unsigned_p && prevn >= n) error (_("Numeric constant too large.")); } prevn = n; @@ -1920,12 +2011,12 @@ parse_number (struct parser_state *par_state, the case where it is we just always shift the value more than once, with fewer bits each time. */ - un = (ULONGEST)n >> 2; + un = n >> 2; if (long_p == 0 - && (un >> (gdbarch_int_bit (parse_gdbarch (par_state)) - 2)) == 0) + && (un >> (gdbarch_int_bit (par_state->gdbarch ()) - 2)) == 0) { high_bit - = ((ULONGEST)1) << (gdbarch_int_bit (parse_gdbarch (par_state)) - 1); + = ((ULONGEST)1) << (gdbarch_int_bit (par_state->gdbarch ()) - 1); /* A large decimal (not hex or octal) constant (between INT_MAX and UINT_MAX) is a long or unsigned long, according to ANSI, @@ -1937,10 +2028,10 @@ parse_number (struct parser_state *par_state, signed_type = parse_type (par_state)->builtin_int; } else if (long_p <= 1 - && (un >> (gdbarch_long_bit (parse_gdbarch (par_state)) - 2)) == 0) + && (un >> (gdbarch_long_bit (par_state->gdbarch ()) - 2)) == 0) { high_bit - = ((ULONGEST)1) << (gdbarch_long_bit (parse_gdbarch (par_state)) - 1); + = ((ULONGEST)1) << (gdbarch_long_bit (par_state->gdbarch ()) - 1); unsigned_type = parse_type (par_state)->builtin_unsigned_long; signed_type = parse_type (par_state)->builtin_long; } @@ -1948,11 +2039,11 @@ parse_number (struct parser_state *par_state, { int shift; if (sizeof (ULONGEST) * HOST_CHAR_BIT - < gdbarch_long_long_bit (parse_gdbarch (par_state))) + < gdbarch_long_long_bit (par_state->gdbarch ())) /* A long long does not fit in a LONGEST. */ shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1); else - shift = (gdbarch_long_long_bit (parse_gdbarch (par_state)) - 1); + shift = (gdbarch_long_long_bit (par_state->gdbarch ()) - 1); high_bit = (ULONGEST) 1 << shift; unsigned_type = parse_type (par_state)->builtin_unsigned_long_long; signed_type = parse_type (par_state)->builtin_long_long; @@ -2004,9 +2095,9 @@ c_parse_escape (const char **ptr, struct obstack *output) if (output) obstack_grow_str (output, "\\x"); ++tokptr; - if (!isxdigit (*tokptr)) + if (!ISXDIGIT (*tokptr)) error (_("\\x escape without a following hex digit")); - while (isxdigit (*tokptr)) + while (ISXDIGIT (*tokptr)) { if (output) obstack_1grow (output, *tokptr); @@ -2029,7 +2120,7 @@ c_parse_escape (const char **ptr, struct obstack *output) if (output) obstack_grow_str (output, "\\"); for (i = 0; - i < 3 && isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9'; + i < 3 && ISDIGIT (*tokptr) && *tokptr != '8' && *tokptr != '9'; ++i) { if (output) @@ -2054,9 +2145,9 @@ c_parse_escape (const char **ptr, struct obstack *output) obstack_1grow (output, *tokptr); } ++tokptr; - if (!isxdigit (*tokptr)) + if (!ISXDIGIT (*tokptr)) error (_("\\%c escape without a following hex digit"), c); - for (i = 0; i < len && isxdigit (*tokptr); ++i) + for (i = 0; i < len && ISXDIGIT (*tokptr); ++i) { if (output) obstack_1grow (output, *tokptr); @@ -2305,7 +2396,10 @@ static const struct token tokentab2[] = {".*", DOT_STAR, BINOP_END, FLAG_CXX} }; -/* Identifier-like tokens. */ +/* Identifier-like tokens. Only type-specifiers than can appear in + multi-word type names (for example 'double' can appear in 'long + double') need to be listed here. type-specifiers that are only ever + single word (like 'float') are handled by the classify_name function. */ static const struct token ident_tokens[] = { {"unsigned", UNSIGNED, OP_NULL, 0}, @@ -2314,6 +2408,8 @@ static const struct token ident_tokens[] = {"struct", STRUCT, OP_NULL, 0}, {"signed", SIGNED_KEYWORD, OP_NULL, 0}, {"sizeof", SIZEOF, OP_NULL, 0}, + {"_Alignof", ALIGNOF, OP_NULL, 0}, + {"alignof", ALIGNOF, OP_NULL, FLAG_CXX}, {"double", DOUBLE_KEYWORD, OP_NULL, 0}, {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX}, {"class", CLASS, OP_NULL, FLAG_CXX}, @@ -2354,77 +2450,41 @@ static const struct token ident_tokens[] = {"typeid", TYPEID, OP_TYPEID, FLAG_CXX} }; -/* When we find that lexptr (the global var defined in parse.c) is - pointing at a macro invocation, we expand the invocation, and call - scan_macro_expansion to save the old lexptr here and point lexptr - into the expanded text. When we reach the end of that, we call - end_macro_expansion to pop back to the value we saved here. The - macro expansion code promises to return only fully-expanded text, - so we don't need to "push" more than one level. - - This is disgusting, of course. It would be cleaner to do all macro - expansion beforehand, and then hand that to lexptr. But we don't - really know where the expression ends. Remember, in a command like - - (gdb) break *ADDRESS if CONDITION - - we evaluate ADDRESS in the scope of the current frame, but we - evaluate CONDITION in the scope of the breakpoint's location. So - it's simply wrong to try to macro-expand the whole thing at once. */ -static const char *macro_original_text; - -/* We save all intermediate macro expansions on this obstack for the - duration of a single parse. The expansion text may sometimes have - to live past the end of the expansion, due to yacc lookahead. - Rather than try to be clever about saving the data for a single - token, we simply keep it all and delete it after parsing has - completed. */ -static struct obstack expansion_obstack; static void scan_macro_expansion (char *expansion) { - char *copy; + const char *copy; /* We'd better not be trying to push the stack twice. */ - gdb_assert (! macro_original_text); + gdb_assert (! cpstate->macro_original_text); /* Copy to the obstack, and then free the intermediate expansion. */ - copy = (char *) obstack_copy0 (&expansion_obstack, expansion, - strlen (expansion)); + copy = obstack_strdup (&cpstate->expansion_obstack, expansion); xfree (expansion); /* Save the old lexptr value, so we can return to it when we're done parsing the expanded text. */ - macro_original_text = lexptr; - lexptr = copy; + cpstate->macro_original_text = pstate->lexptr; + pstate->lexptr = copy; } static int scanning_macro_expansion (void) { - return macro_original_text != 0; + return cpstate->macro_original_text != 0; } static void finished_macro_expansion (void) { /* There'd better be something to pop back to. */ - gdb_assert (macro_original_text); + gdb_assert (cpstate->macro_original_text); /* Pop back to the original text. */ - lexptr = macro_original_text; - macro_original_text = 0; -} - -static void -scan_macro_cleanup (void *dummy) -{ - if (macro_original_text) - finished_macro_expansion (); - - obstack_free (&expansion_obstack, NULL); + pstate->lexptr = cpstate->macro_original_text; + cpstate->macro_original_text = 0; } /* Return true iff the token represents a C++ cast operator. */ @@ -2450,6 +2510,9 @@ static int saw_name_at_eof; operator -- either '.' or ARROW. */ static bool last_was_structop; +/* Depth of parentheses. */ +static int paren_depth; + /* Read one token, getting characters through lexptr. */ static int @@ -2460,7 +2523,6 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) unsigned int i; const char *tokstart; bool saw_structop = last_was_structop; - char *copy; last_was_structop = false; *is_quoted_name = false; @@ -2470,7 +2532,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) /* Check if this is a macro invocation that we need to expand. */ if (! scanning_macro_expansion ()) { - char *expanded = macro_expand_next (&lexptr, + char *expanded = macro_expand_next (&pstate->lexptr, standard_macro_lookup, expression_macro_scope); @@ -2478,18 +2540,18 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) scan_macro_expansion (expanded); } - prev_lexptr = lexptr; + pstate->prev_lexptr = pstate->lexptr; - tokstart = lexptr; + tokstart = pstate->lexptr; /* See if it is a special token of length 3. */ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++) if (strncmp (tokstart, tokentab3[i].oper, 3) == 0) { if ((tokentab3[i].flags & FLAG_CXX) != 0 - && parse_language (par_state)->la_language != language_cplus) + && par_state->language ()->la_language != language_cplus) break; - lexptr += 3; + pstate->lexptr += 3; yylval.opcode = tokentab3[i].opcode; return tokentab3[i].token; } @@ -2499,10 +2561,10 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (strncmp (tokstart, tokentab2[i].oper, 2) == 0) { if ((tokentab2[i].flags & FLAG_CXX) != 0 - && parse_language (par_state)->la_language != language_cplus) + && par_state->language ()->la_language != language_cplus) break; - lexptr += 2; + pstate->lexptr += 2; yylval.opcode = tokentab2[i].opcode; if (tokentab2[i].token == ARROW) last_was_structop = 1; @@ -2528,7 +2590,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) saw_name_at_eof = 0; return COMPLETE; } - else if (parse_completion && saw_structop) + else if (par_state->parse_completion && saw_structop) return COMPLETE; else return 0; @@ -2536,14 +2598,14 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) case ' ': case '\t': case '\n': - lexptr++; + pstate->lexptr++; goto retry; case '[': case '(': paren_depth++; - lexptr++; - if (parse_language (par_state)->la_language == language_objc + pstate->lexptr++; + if (par_state->language ()->la_language == language_objc && c == '[') return OBJC_LBRAC; return c; @@ -2553,25 +2615,25 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (paren_depth == 0) return 0; paren_depth--; - lexptr++; + pstate->lexptr++; return c; case ',': - if (comma_terminates + if (pstate->comma_terminates && paren_depth == 0 && ! scanning_macro_expansion ()) return 0; - lexptr++; + pstate->lexptr++; return c; case '.': /* Might be a floating point number. */ - if (lexptr[1] < '0' || lexptr[1] > '9') + if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9') { last_was_structop = true; goto symbol; /* Nope, must be a symbol. */ } - /* FALL THRU into number case. */ + /* FALL THRU. */ case '0': case '1': @@ -2633,35 +2695,35 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) err_copy[p - tokstart] = 0; error (_("Invalid number \"%s\"."), err_copy); } - lexptr = p; + pstate->lexptr = p; return toktype; } case '@': { const char *p = &tokstart[1]; - size_t len = strlen ("entry"); - if (parse_language (par_state)->la_language == language_objc) + if (par_state->language ()->la_language == language_objc) { size_t len = strlen ("selector"); if (strncmp (p, "selector", len) == 0 - && (p[len] == '\0' || isspace (p[len]))) + && (p[len] == '\0' || ISSPACE (p[len]))) { - lexptr = p + len; + pstate->lexptr = p + len; return SELECTOR; } else if (*p == '"') goto parse_string; } - while (isspace (*p)) + while (ISSPACE (*p)) p++; - if (strncmp (p, "entry", len) == 0 && !isalnum (p[len]) + size_t len = strlen ("entry"); + if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len]) && p[len] != '_') { - lexptr = &p[len]; + pstate->lexptr = &p[len]; return ENTRY; } } @@ -2684,7 +2746,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) case '{': case '}': symbol: - lexptr++; + pstate->lexptr++; return c; case 'L': @@ -2699,8 +2761,8 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) parse_string: { int host_len; - int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval, - &host_len); + int result = parse_string_or_char (tokstart, &pstate->lexptr, + &yylval.tsval, &host_len); if (result == CHAR) { if (host_len == 0) @@ -2708,7 +2770,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) else if (host_len > 2 && c == '\'') { ++tokstart; - namelen = lexptr - tokstart - 1; + namelen = pstate->lexptr - tokstart - 1; *is_quoted_name = true; goto tryname; @@ -2720,16 +2782,14 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) } } - if (!(c == '_' || c == '$' - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) + if (!(c == '_' || c == '$' || c_ident_is_alpha (c))) /* We must have come across a bad character (e.g. ';'). */ error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; for (c = tokstart[namelen]; - (c == '_' || c == '$' || (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');) + (c == '_' || c == '$' || c_ident_is_alnum (c) || c == '<');) { /* Template parameter lists are part of the name. FIXME: This mishandles `print $a<4&&$a>3'. */ @@ -2782,7 +2842,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) return 0; } - lexptr += namelen; + pstate->lexptr += namelen; tryname: @@ -2790,21 +2850,22 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) yylval.sval.length = namelen; /* Catch specific keywords. */ - copy = copy_name (yylval.sval); + std::string copy = copy_name (yylval.sval); for (i = 0; i < sizeof ident_tokens / sizeof ident_tokens[0]; i++) - if (strcmp (copy, ident_tokens[i].oper) == 0) + if (copy == ident_tokens[i].oper) { if ((ident_tokens[i].flags & FLAG_CXX) != 0 - && parse_language (par_state)->la_language != language_cplus) + && par_state->language ()->la_language != language_cplus) break; if ((ident_tokens[i].flags & FLAG_SHADOW) != 0) { struct field_of_this_result is_a_field_of_this; - if (lookup_symbol (copy, expression_context_block, + if (lookup_symbol (copy.c_str (), + pstate->expression_context_block, VAR_DOMAIN, - (parse_language (par_state)->la_language + (par_state->language ()->la_language == language_cplus ? &is_a_field_of_this : NULL)).symbol != NULL) @@ -2821,9 +2882,9 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) } if (*tokstart == '$') - return VARIABLE; + return DOLLAR_VARIABLE; - if (parse_completion && *lexptr == '\0') + if (pstate->parse_completion && *pstate->lexptr == '\0') saw_name_at_eof = 1; yylval.ssym.stoken = yylval.sval; @@ -2834,17 +2895,15 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) } /* An object of this type is pushed on a FIFO by the "outer" lexer. */ -typedef struct +struct token_and_value { int token; YYSTYPE value; -} token_and_value; - -DEF_VEC_O (token_and_value); +}; /* A FIFO of tokens that have been read but not yet returned to the parser. */ -static VEC (token_and_value) *token_fifo; +static std::vector token_fifo; /* Non-zero if the lexer should return tokens from the FIFO. */ static int popping; @@ -2865,17 +2924,16 @@ classify_name (struct parser_state *par_state, const struct block *block, bool is_quoted_name, bool is_after_structop) { struct block_symbol bsym; - char *copy; struct field_of_this_result is_a_field_of_this; - copy = copy_name (yylval.sval); + std::string copy = copy_name (yylval.sval); /* Initialize this in case we *don't* use it in this call; that way we can refer to it unconditionally below. */ memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this)); - bsym = lookup_symbol (copy, block, VAR_DOMAIN, - parse_language (par_state)->la_name_of_this + bsym = lookup_symbol (copy.c_str (), block, VAR_DOMAIN, + par_state->language ()->la_name_of_this ? &is_a_field_of_this : NULL); if (bsym.symbol && SYMBOL_CLASS (bsym.symbol) == LOC_BLOCK) @@ -2897,7 +2955,7 @@ classify_name (struct parser_state *par_state, const struct block *block, { struct field_of_this_result inner_is_a_field_of_this; - bsym = lookup_symbol (copy, block, STRUCT_DOMAIN, + bsym = lookup_symbol (copy.c_str (), block, STRUCT_DOMAIN, &inner_is_a_field_of_this); if (bsym.symbol != NULL) { @@ -2917,7 +2975,7 @@ classify_name (struct parser_state *par_state, const struct block *block, /* See if it's a file name. */ struct symtab *symtab; - symtab = lookup_symtab (copy); + symtab = lookup_symtab (copy.c_str ()); if (symtab) { yylval.bval = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), @@ -2934,15 +2992,17 @@ classify_name (struct parser_state *par_state, const struct block *block, } /* See if it's an ObjC classname. */ - if (parse_language (par_state)->la_language == language_objc && !bsym.symbol) + if (par_state->language ()->la_language == language_objc && !bsym.symbol) { - CORE_ADDR Class = lookup_objc_class (parse_gdbarch (par_state), copy); + CORE_ADDR Class = lookup_objc_class (par_state->gdbarch (), + copy.c_str ()); if (Class) { struct symbol *sym; yylval.theclass.theclass = Class; - sym = lookup_struct_typedef (copy, expression_context_block, 1); + sym = lookup_struct_typedef (copy.c_str (), + par_state->expression_context_block, 1); if (sym) yylval.theclass.type = SYMBOL_TYPE (sym); return CLASSNAME; @@ -2957,7 +3017,7 @@ classify_name (struct parser_state *par_state, const struct block *block, || (copy[0] >= 'A' && copy[0] < 'A' + input_radix - 10))) { YYSTYPE newlval; /* Its value is ignored. */ - int hextype = parse_number (par_state, copy, yylval.sval.length, + int hextype = parse_number (par_state, copy.c_str (), yylval.sval.length, 0, &newlval); if (hextype == INT) @@ -2973,9 +3033,9 @@ classify_name (struct parser_state *par_state, const struct block *block, yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL; if (bsym.symbol == NULL - && parse_language (par_state)->la_language == language_cplus + && par_state->language ()->la_language == language_cplus && is_a_field_of_this.type == NULL - && lookup_minimal_symbol (copy, NULL, NULL).minsym == NULL) + && lookup_minimal_symbol (copy.c_str (), NULL, NULL).minsym == NULL) return UNKNOWN_CPP_NAME; return NAME; @@ -2990,7 +3050,6 @@ classify_inner_name (struct parser_state *par_state, const struct block *block, struct type *context) { struct type *type; - char *copy; if (context == NULL) return classify_name (par_state, block, false, false); @@ -2999,16 +3058,18 @@ classify_inner_name (struct parser_state *par_state, if (!type_aggregate_p (type)) return ERROR; - copy = copy_name (yylval.ssym.stoken); + std::string copy = copy_name (yylval.ssym.stoken); /* N.B. We assume the symbol can only be in VAR_DOMAIN. */ - yylval.ssym.sym = cp_lookup_nested_symbol (type, copy, block, VAR_DOMAIN); + yylval.ssym.sym = cp_lookup_nested_symbol (type, copy.c_str (), block, + VAR_DOMAIN); /* If no symbol was found, search for a matching base class named COPY. This will allow users to enter qualified names of class members relative to the `this' pointer. */ if (yylval.ssym.sym.symbol == NULL) { - struct type *base_type = cp_find_type_baseclass_by_name (type, copy); + struct type *base_type = cp_find_type_baseclass_by_name (type, + copy.c_str ()); if (base_type != NULL) { @@ -3027,7 +3088,8 @@ classify_inner_name (struct parser_state *par_state, named COPY when we really wanted a base class of the same name. Double-check this case by looking for a base class. */ { - struct type *base_type = cp_find_type_baseclass_by_name (type, copy); + struct type *base_type + = cp_find_type_baseclass_by_name (type, copy.c_str ()); if (base_type != NULL) { @@ -3069,7 +3131,7 @@ yylex (void) const struct block *search_block; bool is_quoted_name, last_lex_was_structop; - if (popping && !VEC_empty (token_and_value, token_fifo)) + if (popping && !token_fifo.empty ()) goto do_pop; popping = 0; @@ -3080,9 +3142,9 @@ yylex (void) name-like token. */ current.token = lex_one_token (pstate, &is_quoted_name); if (current.token == NAME) - current.token = classify_name (pstate, expression_context_block, + current.token = classify_name (pstate, pstate->expression_context_block, is_quoted_name, last_lex_was_structop); - if (parse_language (pstate)->la_language != language_cplus + if (pstate->language ()->la_language != language_cplus || (current.token != TYPENAME && current.token != COLONCOLON && current.token != FILENAME)) return current.token; @@ -3090,7 +3152,7 @@ yylex (void) /* Read any sequence of alternating "::" and name-like tokens into the token FIFO. */ current.value = yylval; - VEC_safe_push (token_and_value, token_fifo, ¤t); + token_fifo.push_back (current); last_was_coloncolon = current.token == COLONCOLON; while (1) { @@ -3100,7 +3162,7 @@ yylex (void) Subsequent ones do not have any special meaning. */ current.token = lex_one_token (pstate, &ignore); current.value = yylval; - VEC_safe_push (token_and_value, token_fifo, ¤t); + token_fifo.push_back (current); if ((last_was_coloncolon && current.token != NAME) || (!last_was_coloncolon && current.token != COLONCOLON)) @@ -3111,10 +3173,10 @@ yylex (void) /* We always read one extra token, so compute the number of tokens to examine accordingly. */ - last_to_examine = VEC_length (token_and_value, token_fifo) - 2; + last_to_examine = token_fifo.size () - 2; next_to_examine = 0; - current = *VEC_index (token_and_value, token_fifo, next_to_examine); + current = token_fifo[next_to_examine]; ++next_to_examine; name_obstack.clear (); @@ -3126,7 +3188,7 @@ yylex (void) else { gdb_assert (current.token == TYPENAME); - search_block = expression_context_block; + search_block = pstate->expression_context_block; obstack_grow (&name_obstack, current.value.sval.ptr, current.value.sval.length); context_type = current.value.tsym.type; @@ -3138,16 +3200,16 @@ yylex (void) while (next_to_examine <= last_to_examine) { - token_and_value *next; + token_and_value next; - next = VEC_index (token_and_value, token_fifo, next_to_examine); + next = token_fifo[next_to_examine]; ++next_to_examine; - if (next->token == NAME && last_was_coloncolon) + if (next.token == NAME && last_was_coloncolon) { int classification; - yylval = next->value; + yylval = next.value; classification = classify_inner_name (pstate, search_block, context_type); /* We keep going until we either run out of names, or until @@ -3164,8 +3226,8 @@ yylex (void) /* We don't want to put a leading "::" into the name. */ obstack_grow_str (&name_obstack, "::"); } - obstack_grow (&name_obstack, next->value.sval.ptr, - next->value.sval.length); + obstack_grow (&name_obstack, next.value.sval.ptr, + next.value.sval.length); yylval.sval.ptr = (const char *) obstack_base (&name_obstack); yylval.sval.length = obstack_object_size (&name_obstack); @@ -3179,7 +3241,7 @@ yylex (void) context_type = yylval.tsym.type; } - else if (next->token == COLONCOLON && !last_was_coloncolon) + else if (next.token == COLONCOLON && !last_was_coloncolon) last_was_coloncolon = 1; else { @@ -3193,18 +3255,19 @@ yylex (void) if (checkpoint > 0) { current.value.sval.ptr - = (const char *) obstack_copy0 (&expansion_obstack, - current.value.sval.ptr, - current.value.sval.length); + = obstack_strndup (&cpstate->expansion_obstack, + current.value.sval.ptr, + current.value.sval.length); - VEC_replace (token_and_value, token_fifo, 0, ¤t); + token_fifo[0] = current; if (checkpoint > 1) - VEC_block_remove (token_and_value, token_fifo, 1, checkpoint - 1); + token_fifo.erase (token_fifo.begin () + 1, + token_fifo.begin () + checkpoint); } do_pop: - current = *VEC_index (token_and_value, token_fifo, 0); - VEC_ordered_remove (token_and_value, token_fifo, 0); + current = token_fifo[0]; + token_fifo.erase (token_fifo.begin ()); yylval = current.value; return current.token; } @@ -3212,34 +3275,26 @@ yylex (void) int c_parse (struct parser_state *par_state) { - int result; - struct cleanup *back_to; - /* Setting up the parser state. */ scoped_restore pstate_restore = make_scoped_restore (&pstate); gdb_assert (par_state != NULL); pstate = par_state; - /* Note that parsing (within yyparse) freely installs cleanups - assuming they'll be run here (below). */ + c_parse_state cstate; + scoped_restore cstate_restore = make_scoped_restore (&cpstate, &cstate); - back_to = make_cleanup (free_current_contents, &expression_macro_scope); + gdb::unique_xmalloc_ptr macro_scope; - /* Set up the scope for macro expansion. */ - expression_macro_scope = NULL; - - if (expression_context_block) - expression_macro_scope - = sal_macro_scope (find_pc_line (expression_context_pc, 0)); + if (par_state->expression_context_block) + macro_scope + = sal_macro_scope (find_pc_line (par_state->expression_context_pc, 0)); else - expression_macro_scope = default_macro_scope (); - if (! expression_macro_scope) - expression_macro_scope = user_macro_scope (); + macro_scope = default_macro_scope (); + if (! macro_scope) + macro_scope = user_macro_scope (); - /* Initialize macro expansion code. */ - obstack_init (&expansion_obstack); - gdb_assert (! macro_original_text); - make_cleanup (scan_macro_cleanup, 0); + scoped_restore restore_macro_scope + = make_scoped_restore (&expression_macro_scope, macro_scope.get ()); scoped_restore restore_yydebug = make_scoped_restore (&yydebug, parser_debug); @@ -3247,15 +3302,13 @@ c_parse (struct parser_state *par_state) /* Initialize some state used by the lexer. */ last_was_structop = false; saw_name_at_eof = 0; + paren_depth = 0; - VEC_free (token_and_value, token_fifo); + token_fifo.clear (); popping = 0; name_obstack.clear (); - result = yyparse (); - do_cleanups (back_to); - - return result; + return yyparse (); } #ifdef YYBISON @@ -3287,14 +3340,14 @@ c_print_token (FILE *file, int type, YYSTYPE value) break; case NSSTRING: - case VARIABLE: - parser_fprintf (file, "sval<%s>", copy_name (value.sval)); + case DOLLAR_VARIABLE: + parser_fprintf (file, "sval<%s>", copy_name (value.sval).c_str ()); break; case TYPENAME: parser_fprintf (file, "tsym", TYPE_SAFE_NAME (value.tsym.type), - copy_name (value.tsym.stoken)); + copy_name (value.tsym.stoken).c_str ()); break; case NAME: @@ -3302,9 +3355,9 @@ c_print_token (FILE *file, int type, YYSTYPE value) case NAME_OR_INT: case BLOCKNAME: parser_fprintf (file, "ssym", - copy_name (value.ssym.stoken), + copy_name (value.ssym.stoken).c_str (), (value.ssym.sym.symbol == NULL - ? "(null)" : SYMBOL_PRINT_NAME (value.ssym.sym.symbol)), + ? "(null)" : value.ssym.sym.symbol->print_name ()), value.ssym.is_a_field_of_this); break; @@ -3316,11 +3369,11 @@ c_print_token (FILE *file, int type, YYSTYPE value) #endif -void +static void yyerror (const char *msg) { - if (prev_lexptr) - lexptr = prev_lexptr; + if (pstate->prev_lexptr) + pstate->lexptr = pstate->prev_lexptr; - error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), msg, pstate->lexptr); }