X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=e7d0a0dc4ad398f514ccb866b1cd6eb27324c3dc;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=2753c6ec5d17f308addc5e5753cb95be6d590719;hpb=d7e747318f4d04af033f16325f9b6d74f67079ec;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 2753c6ec5d..e7d0a0dc4a 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-2017 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -42,19 +42,21 @@ #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 */ #include "charset.h" #include "block.h" #include "cp-support.h" -#include "dfp.h" #include "macroscope.h" #include "objc-lang.h" #include "typeprint.h" #include "cp-abi.h" +#include "type-stack.h" +#include "target-float.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). */ @@ -66,11 +68,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 (char *); +static void yyerror (const char *); static int type_aggregate_p (struct type *); @@ -87,14 +136,10 @@ static int type_aggregate_p (struct type *); LONGEST val; struct type *type; } typed_val_int; - struct { - DOUBLEST dval; - struct type *type; - } typed_val_float; struct { gdb_byte val[16]; struct type *type; - } typed_val_decfloat; + } typed_val_float; struct type *tval; struct stoken sval; struct typed_stoken tsval; @@ -105,7 +150,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; @@ -117,7 +162,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); @@ -127,9 +173,9 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); #endif %} -%type exp exp1 type_exp start variable qualified_name lcurly +%type exp exp1 type_exp start variable qualified_name lcurly function_method %type rcurly -%type type typebase +%type type typebase scalar_type %type nonempty_typelist func_mod parameter_typelist /* %type block */ @@ -140,9 +186,8 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %type ptr_operator_ts abs_decl direct_abs_decl -%token INT -%token FLOAT -%token DECFLOAT +%token INT COMPLEX_INT +%token FLOAT COMPLEX_FLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -161,7 +206,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 @@ -179,7 +224,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 @@ -193,8 +238,10 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD +%token RESTRICT ATOMIC +%token FLOAT_KEYWORD COMPLEX -%token VARIABLE +%token DOLLAR_VARIABLE %token ASSIGN_MODIFY @@ -313,14 +360,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); } @@ -328,7 +379,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; @@ -343,7 +394,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); } @@ -361,14 +412,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); } @@ -376,7 +427,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; @@ -391,7 +442,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); } @@ -426,14 +477,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(); @@ -490,21 +542,33 @@ 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); } + ; + +/* This is here to disambiguate with the production for + "func()::static_var" further below, which uses + function_method_void. */ +exp : exp '(' ')' %prec ARROW + { pstate->start_arglist (); + write_exp_elt_opcode (pstate, OP_FUNCALL); + write_exp_elt_longcst (pstate, + pstate->end_arglist ()); write_exp_elt_opcode (pstate, OP_FUNCALL); } ; + 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); @@ -513,52 +577,86 @@ 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++; } ; -exp : 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); +function_method: exp '(' parameter_typelist ')' const_or_volatile + { + 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, + (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, + 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); + } + ; + +exp : function_method + ; + +/* Normally we must interpret "func()" as a function call, instead of + a type. The user needs to write func(void) to disambiguate. + However, in the "func()::static_var" case, there's no + ambiguity. */ +function_method_void_or_typelist: function_method + | function_method_void + ; + +exp : function_method_void_or_typelist COLONCOLON name + { + write_exp_elt_opcode (pstate, OP_FUNC_STATIC_VAR); + write_exp_string (pstate, $3); + write_exp_elt_opcode (pstate, OP_FUNC_STATIC_VAR); } ; rcurly : '}' - { $$ = end_arglist () - 1; } + { $$ = pstate->end_arglist () - 1; } ; exp : lcurly arglist rcurly %prec ARROW { write_exp_elt_opcode (pstate, OP_ARRAY); @@ -679,6 +777,22 @@ exp : INT write_exp_elt_opcode (pstate, OP_LONG); } ; +exp : COMPLEX_INT + { + write_exp_elt_opcode (pstate, OP_LONG); + write_exp_elt_type (pstate, TYPE_TARGET_TYPE ($1.type)); + write_exp_elt_longcst (pstate, 0); + write_exp_elt_opcode (pstate, OP_LONG); + write_exp_elt_opcode (pstate, OP_LONG); + write_exp_elt_type (pstate, TYPE_TARGET_TYPE ($1.type)); + write_exp_elt_longcst (pstate, (LONGEST) ($1.val)); + write_exp_elt_opcode (pstate, OP_LONG); + write_exp_elt_opcode (pstate, OP_COMPLEX); + write_exp_elt_type (pstate, $1.type); + write_exp_elt_opcode (pstate, OP_COMPLEX); + } + ; + exp : CHAR { struct stoken_vector vec; @@ -702,23 +816,37 @@ exp : NAME_OR_INT exp : FLOAT - { write_exp_elt_opcode (pstate, OP_DOUBLE); + { write_exp_elt_opcode (pstate, OP_FLOAT); write_exp_elt_type (pstate, $1.type); - write_exp_elt_dblcst (pstate, $1.dval); - write_exp_elt_opcode (pstate, OP_DOUBLE); } + write_exp_elt_floatcst (pstate, $1.val); + write_exp_elt_opcode (pstate, OP_FLOAT); } ; -exp : DECFLOAT - { write_exp_elt_opcode (pstate, OP_DECFLOAT); +exp : COMPLEX_FLOAT + { + struct type *underlying + = TYPE_TARGET_TYPE ($1.type); + + write_exp_elt_opcode (pstate, OP_FLOAT); + write_exp_elt_type (pstate, underlying); + gdb_byte val[16]; + target_float_from_host_double (val, underlying, 0); + write_exp_elt_floatcst (pstate, val); + write_exp_elt_opcode (pstate, OP_FLOAT); + write_exp_elt_opcode (pstate, OP_FLOAT); + write_exp_elt_type (pstate, underlying); + write_exp_elt_floatcst (pstate, $1.val); + write_exp_elt_opcode (pstate, OP_FLOAT); + write_exp_elt_opcode (pstate, OP_COMPLEX); write_exp_elt_type (pstate, $1.type); - write_exp_elt_decfloatcst (pstate, $1.val); - write_exp_elt_opcode (pstate, OP_DECFLOAT); } + write_exp_elt_opcode (pstate, OP_COMPLEX); + } ; exp : variable ; -exp : VARIABLE +exp : DOLLAR_VARIABLE { write_dollar_variable (pstate, $1); } @@ -735,8 +863,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); @@ -744,7 +871,7 @@ exp : SIZEOF '(' type ')' %prec UNARY says of sizeof: "When applied to a reference or a reference type, the result is the size of the referenced type." */ - if (TYPE_CODE (type) == TYPE_CODE_REF) + if (TYPE_IS_REFERENCE (type)) type = check_typedef (TYPE_TARGET_TYPE (type)); write_exp_elt_longcst (pstate, (LONGEST) TYPE_LENGTH (type)); @@ -872,7 +999,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 { @@ -881,13 +1008,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); } ; @@ -898,7 +1027,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); @@ -907,20 +1036,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)) - { - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; - } + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); @@ -967,22 +1093,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) { @@ -993,13 +1120,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 ()); } ; @@ -1009,27 +1137,31 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) + pstate->block_tracker->update (sym); + + /* 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 { - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; + 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); } - - 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. */ - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; + 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); @@ -1038,66 +1170,101 @@ variable: name_not_typename } else { - struct bound_minimal_symbol msymbol; - char *arg = copy_name ($1.stoken); + std::string arg = copy_name ($1.stoken); - msymbol = - lookup_bound_minimal_symbol (arg); - 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.")); + bound_minimal_symbol msymbol + = 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."), + arg.c_str ()); + } + + /* This minsym might be an alias for + another function. See if we can find + the debug symbol for the target, and + if so, use it instead, since it has + return type / prototype info. This + is important for example for "p + *__errno_location()". */ + symbol *alias_target + = ((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); + write_exp_elt_block + (pstate, SYMBOL_BLOCK_VALUE (alias_target)); + write_exp_elt_sym (pstate, alias_target); + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + } else - error (_("No symbol \"%s\" in current context."), - copy_name ($1.stoken)); + write_exp_msymbol (pstate, msymbol); } } ; -space_identifier : '@' NAME - { insert_type_address_space (pstate, copy_name ($2.stoken)); } - ; - const_or_volatile: const_or_volatile_noopt | ; -cv_with_space_id : const_or_volatile space_identifier const_or_volatile +single_qualifier: + CONST_KEYWORD + { cpstate->type_stack.insert (tp_const); } + | VOLATILE_KEYWORD + { cpstate->type_stack.insert (tp_volatile); } + | ATOMIC + { cpstate->type_stack.insert (tp_atomic); } + | RESTRICT + { cpstate->type_stack.insert (tp_restrict); } + | '@' NAME + { + cpstate->type_stack.insert (pstate, + copy_name ($2.stoken).c_str ()); + } ; -const_or_volatile_or_space_identifier_noopt: cv_with_space_id - | const_or_volatile_noopt +qualifier_seq_noopt: + single_qualifier + | qualifier_seq single_qualifier ; -const_or_volatile_or_space_identifier: - const_or_volatile_or_space_identifier_noopt +qualifier_seq: + qualifier_seq_noopt | ; ptr_operator: ptr_operator '*' - { insert_type (tp_pointer); } - const_or_volatile_or_space_identifier + { cpstate->type_stack.insert (tp_pointer); } + qualifier_seq | '*' - { insert_type (tp_pointer); } - const_or_volatile_or_space_identifier + { cpstate->type_stack.insert (tp_pointer); } + qualifier_seq | '&' - { insert_type (tp_reference); } + { cpstate->type_stack.insert (tp_reference); } | '&' ptr_operator - { insert_type (tp_reference); } + { cpstate->type_stack.insert (tp_reference); } + | ANDAND + { cpstate->type_stack.insert (tp_rvalue_reference); } + | ANDAND ptr_operator + { 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 ; @@ -1106,28 +1273,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 ($$); } ; @@ -1142,7 +1313,10 @@ array_mod: '[' ']' ; func_mod: '(' ')' - { $$ = NULL; } + { + $$ = new std::vector; + cpstate->type_lists.emplace_back ($$); + } | '(' parameter_typelist ')' { $$ = $2; } ; @@ -1158,208 +1332,214 @@ func_mod: '(' ')' type : ptype ; -typebase /* Implements (approximately): (type-qualifier)* type-specifier */ - : TYPENAME - { $$ = $1.type; } - | INT_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), +/* A helper production that recognizes scalar types that can validly + be used with _Complex. */ + +scalar_type: + INT_KEYWORD + { $$ = 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); } + | FLOAT_KEYWORD + { $$ = lookup_typename (pstate->language (), + "float", + NULL, 0); } | LONG DOUBLE_KEYWORD - { $$ = lookup_typename (parse_language (pstate), - parse_gdbarch (pstate), + { $$ = lookup_typename (pstate->language (), "long double", - (struct block *) NULL, + NULL, 0); } + | UNSIGNED type_name + { $$ = lookup_unsigned_typename (pstate->language (), + $2.type->name ()); } + | UNSIGNED + { $$ = lookup_unsigned_typename (pstate->language (), + "int"); } + | SIGNED_KEYWORD type_name + { $$ = lookup_signed_typename (pstate->language (), + $2.type->name ()); } + | SIGNED_KEYWORD + { $$ = lookup_signed_typename (pstate->language (), + "int"); } + ; + +/* 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; } + | scalar_type + { $$ = $1; } + | COMPLEX scalar_type + { + $$ = init_complex_type (nullptr, $2); + } | 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), - TYPE_NAME($2.type)); } - | UNSIGNED - { $$ = lookup_unsigned_typename (parse_language (pstate), - parse_gdbarch (pstate), - "int"); } - | SIGNED_KEYWORD type_name - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), - TYPE_NAME($2.type)); } - | SIGNED_KEYWORD - { $$ = lookup_signed_typename (parse_language (pstate), - parse_gdbarch (pstate), - "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); } - | typebase const_or_volatile_or_space_identifier_noopt - { $$ = follow_types ($1); } + | qualifier_seq_noopt typebase + { $$ = cpstate->type_stack.follow_types ($2); } + | typebase qualifier_seq_noopt + { $$ = cpstate->type_stack.follow_types ($1); } ; type_name: TYPENAME @@ -1367,24 +1547,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"); } ; @@ -1394,7 +1571,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; } @@ -1403,13 +1580,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; } ; @@ -1417,13 +1597,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. */ @@ -1435,13 +1615,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 @@ -1483,7 +1663,7 @@ oper: OPERATOR NEW | OPERATOR '>' { $$ = operator_stoken (">"); } | OPERATOR ASSIGN_MODIFY - { const char *op = "unknown"; + { const char *op = " unknown"; switch ($2) { case BINOP_RSH: @@ -1559,11 +1739,32 @@ oper: OPERATOR NEW c_print_type ($2, NULL, &buf, -1, 0, &type_print_raw_options); - $$ = operator_stoken (buf.c_str ()); + std::string name = std::move (buf.string ()); + + /* This also needs canonicalization. */ + gdb::unique_xmalloc_ptr canon + = cp_canonicalize_string (name.c_str ()); + if (canon != nullptr) + name = canon.get (); + $$ = operator_stoken ((" " + name).c_str ()); } ; - +/* 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'. */ +field_name + : name + | DOUBLE_KEYWORD { $$ = typename_stoken ("double"); } + | FLOAT_KEYWORD { $$ = typename_stoken ("float"); } + | 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; } @@ -1587,10 +1788,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; } @@ -1621,18 +1823,27 @@ write_destructor_name (struct parser_state *par_state, struct stoken token) static struct stoken operator_stoken (const char *op) { - static const char *operator_string = "operator"; struct stoken st = { NULL, 0 }; char *buf; - st.length = strlen (operator_string) + strlen (op); + st.length = CP_OPERATOR_LEN + strlen (op); buf = (char *) malloc (st.length + 1); - strcpy (buf, operator_string); + strcpy (buf, CP_OPERATOR_STR); strcat (buf, 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; }; @@ -1641,40 +1852,37 @@ operator_stoken (const char *op) static int type_aggregate_p (struct type *type) { - return (TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION - || TYPE_CODE (type) == TYPE_CODE_NAMESPACE - || (TYPE_CODE (type) == TYPE_CODE_ENUM + return (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION + || type->code () == TYPE_CODE_NAMESPACE + || (type->code () == TYPE_CODE_ENUM && TYPE_DECLARED_CLASS (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) { - if (type != NULL && TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) + type = (*params)[ix]; + if (type != NULL && check_typedef (type)->code () == 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")); } } } @@ -1689,10 +1897,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; @@ -1703,7 +1909,10 @@ parse_number (struct parser_state *par_state, /* Number of "L" suffixes encountered. */ int long_p = 0; - /* We have found a "L" or "U" suffix. */ + /* Imaginary number. */ + bool imaginary_p = false; + + /* We have found a "L" or "U" (or "i") suffix. */ int found_suffix = 0; ULONGEST high_bit; @@ -1716,50 +1925,61 @@ parse_number (struct parser_state *par_state, if (parsed_float) { - /* If it ends at "df", "dd" or "dl", take it as type of decimal floating - point. Return DECFLOAT. */ + if (len >= 1 && p[len - 1] == 'i') + { + imaginary_p = true; + --len; + } + /* Handle suffixes for decimal floating-point: "df", "dd" or "dl". */ if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_decfloat; - decimal_from_string (putithere->typed_val_decfloat.val, 4, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; } - - if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd') + else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_decdouble; - decimal_from_string (putithere->typed_val_decfloat.val, 8, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; } - - if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l') + else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_declong; - decimal_from_string (putithere->typed_val_decfloat.val, 16, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; } + /* Handle suffixes: 'f' for float, 'l' for long double. */ + 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') + { + putithere->typed_val_float.type + = parse_type (par_state)->builtin_long_double; + len -= 1; + } + /* Default type for floating-point literals is double. */ + else + { + putithere->typed_val_float.type + = parse_type (par_state)->builtin_double; + } + + if (!parse_float (p, len, + putithere->typed_val_float.type, + putithere->typed_val_float.val)) + return ERROR; - if (! parse_c_float (parse_gdbarch (par_state), p, len, - &putithere->typed_val_float.dval, - &putithere->typed_val_float.type)) - return ERROR; - return FLOAT; + if (imaginary_p) + putithere->typed_val_float.type + = init_complex_type (nullptr, putithere->typed_val_float.type); + + return imaginary_p ? COMPLEX_FLOAT : FLOAT; } /* Handle base-switching prefixes 0x, 0t, 0d, 0 */ @@ -1808,7 +2028,7 @@ parse_number (struct parser_state *par_state, c = *p++; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if (c != 'l' && c != 'u') + if (c != 'l' && c != 'u' && c != 'i') n *= base; if (c >= '0' && c <= '9') { @@ -1834,6 +2054,11 @@ parse_number (struct parser_state *par_state, unsigned_p = 1; found_suffix = 1; } + else if (c == 'i') + { + imaginary_p = true; + found_suffix = 1; + } else return ERROR; /* Char not a digit */ } @@ -1843,15 +2068,15 @@ parse_number (struct parser_state *par_state, /* Portably test for overflow (only works for nonzero values, so make a second check for zero). FIXME: Can't we just make n and prevn unsigned and avoid this? */ - if (c != 'l' && c != 'u' && (prevn >= n) && n != 0) + if (c != 'l' && c != 'u' && c != 'i' && (prevn >= n) && n != 0) unsigned_p = 1; /* Try something unsigned */ /* Portably test for unsigned overflow. FIXME: This check is wrong; for example it doesn't find overflow on 0x123456789 when LONGEST is 32 bits. */ - if (c != 'l' && c != 'u' && n != 0) + if (c != 'l' && c != 'u' && c != 'i' && n != 0) { - if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n)) + if (unsigned_p && prevn >= n) error (_("Numeric constant too large.")); } prevn = n; @@ -1869,12 +2094,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, @@ -1886,10 +2111,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; } @@ -1897,11 +2122,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; @@ -1921,7 +2146,11 @@ parse_number (struct parser_state *par_state, putithere->typed_val_int.type = signed_type; } - return INT; + if (imaginary_p) + putithere->typed_val_int.type + = init_complex_type (nullptr, putithere->typed_val_int.type); + + return imaginary_p ? COMPLEX_INT : INT; } /* Temporary obstack used for holding strings. */ @@ -1953,9 +2182,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); @@ -1978,7 +2207,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) @@ -2003,9 +2232,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); @@ -2203,17 +2432,21 @@ enum token_flag FLAG_CXX = 1, + /* If this bit is set, the token is C-only. */ + + FLAG_C = 2, + /* If this bit is set, the token is conditional: if there is a symbol of the same name, then the token is a symbol; otherwise, the token is a keyword. */ - FLAG_SHADOW = 2 + FLAG_SHADOW = 4 }; DEF_ENUM_FLAGS_TYPE (enum token_flag, token_flags); struct token { - char *oper; + const char *oper; int token; enum exp_opcode opcode; token_flags flags; @@ -2254,7 +2487,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 'char') are handled by the classify_name function. */ static const struct token ident_tokens[] = { {"unsigned", UNSIGNED, OP_NULL, 0}, @@ -2263,14 +2499,24 @@ 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}, + {"float", FLOAT_KEYWORD, OP_NULL, 0}, {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX}, {"class", CLASS, OP_NULL, FLAG_CXX}, {"union", UNION, OP_NULL, 0}, {"short", SHORT, OP_NULL, 0}, {"const", CONST_KEYWORD, OP_NULL, 0}, + {"restrict", RESTRICT, OP_NULL, FLAG_C | FLAG_SHADOW}, + {"__restrict__", RESTRICT, OP_NULL, 0}, + {"__restrict", RESTRICT, OP_NULL, 0}, + {"_Atomic", ATOMIC, OP_NULL, 0}, {"enum", ENUM, OP_NULL, 0}, {"long", LONG, OP_NULL, 0}, + {"_Complex", COMPLEX, OP_NULL, 0}, + {"__complex__", COMPLEX, OP_NULL, 0}, + {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX}, {"int", INT_KEYWORD, OP_NULL, 0}, {"new", NEW, OP_NULL, FLAG_CXX}, @@ -2303,77 +2549,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. */ @@ -2396,31 +2606,32 @@ static struct macro_scope *expression_macro_scope; static int saw_name_at_eof; /* This is set if the previously-returned token was a structure - operator -- either '.' or ARROW. This is used only when parsing to - do field name completion. */ -static int last_was_structop; + 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 -lex_one_token (struct parser_state *par_state, int *is_quoted_name) +lex_one_token (struct parser_state *par_state, bool *is_quoted_name) { int c; int namelen; unsigned int i; const char *tokstart; - int saw_structop = last_was_structop; - char *copy; + bool saw_structop = last_was_structop; - last_was_structop = 0; - *is_quoted_name = 0; + last_was_structop = false; + *is_quoted_name = false; retry: /* 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); @@ -2428,18 +2639,19 @@ lex_one_token (struct parser_state *par_state, int *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; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); - lexptr += 3; + pstate->lexptr += 3; yylval.opcode = tokentab3[i].opcode; return tokentab3[i].token; } @@ -2449,12 +2661,13 @@ lex_one_token (struct parser_state *par_state, int *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; + gdb_assert ((tokentab2[i].flags & FLAG_C) == 0); - lexptr += 2; + pstate->lexptr += 2; yylval.opcode = tokentab2[i].opcode; - if (parse_completion && tokentab2[i].token == ARROW) + if (tokentab2[i].token == ARROW) last_was_structop = 1; return tokentab2[i].token; } @@ -2478,7 +2691,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) saw_name_at_eof = 0; return COMPLETE; } - else if (saw_structop) + else if (par_state->parse_completion && saw_structop) return COMPLETE; else return 0; @@ -2486,14 +2699,14 @@ lex_one_token (struct parser_state *par_state, int *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; @@ -2503,26 +2716,25 @@ lex_one_token (struct parser_state *par_state, int *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') { - if (parse_completion) - last_was_structop = 1; + last_was_structop = true; goto symbol; /* Nope, must be a symbol. */ } - /* FALL THRU into number case. */ + /* FALL THRU. */ case '0': case '1': @@ -2584,35 +2796,35 @@ lex_one_token (struct parser_state *par_state, int *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; } } @@ -2635,7 +2847,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) case '{': case '}': symbol: - lexptr++; + pstate->lexptr++; return c; case 'L': @@ -2650,8 +2862,8 @@ lex_one_token (struct parser_state *par_state, int *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) @@ -2659,8 +2871,8 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) else if (host_len > 2 && c == '\'') { ++tokstart; - namelen = lexptr - tokstart - 1; - *is_quoted_name = 1; + namelen = pstate->lexptr - tokstart - 1; + *is_quoted_name = true; goto tryname; } @@ -2671,16 +2883,14 @@ lex_one_token (struct parser_state *par_state, int *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'. */ @@ -2733,7 +2943,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) return 0; } - lexptr += namelen; + pstate->lexptr += namelen; tryname: @@ -2741,21 +2951,26 @@ lex_one_token (struct parser_state *par_state, int *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_C) != 0 + && par_state->language ()->la_language != language_c + && par_state->language ()->la_language != language_objc) 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) @@ -2772,9 +2987,9 @@ lex_one_token (struct parser_state *par_state, int *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; @@ -2785,47 +3000,45 @@ lex_one_token (struct parser_state *par_state, int *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; /* Temporary storage for c_lex; this holds symbol names as they are built up. */ -static struct obstack name_obstack; +auto_obstack name_obstack; /* Classify a NAME token. The contents of the token are in `yylval'. Updates yylval and returns the new token type. BLOCK is the block in which lookups start; this can be NULL to mean the global scope. IS_QUOTED_NAME is non-zero if the name token was originally quoted - in single quotes. */ + in single quotes. IS_AFTER_STRUCTOP is true if this name follows + a structure operator -- either '.' or ARROW */ static int classify_name (struct parser_state *par_state, const struct block *block, - int is_quoted_name) + 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) @@ -2847,7 +3060,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) { @@ -2856,16 +3069,18 @@ classify_name (struct parser_state *par_state, const struct block *block, } } - /* If we found a field, then we want to prefer it over a + /* If we found a field on the "this" object, or we are looking + up a field on a struct, then we want to prefer it over a filename. However, if the name was quoted, then it is better to check for a filename or a block, since this is the only way the user has of requiring the extension to be used. */ - if (is_a_field_of_this.type == NULL || is_quoted_name) + if ((is_a_field_of_this.type == NULL && !is_after_structop) + || is_quoted_name) { /* 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), @@ -2882,15 +3097,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; @@ -2905,7 +3122,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) @@ -2921,9 +3138,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; @@ -2938,25 +3155,26 @@ 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, 0); + return classify_name (par_state, block, false, false); type = check_typedef (context); 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) { @@ -2975,7 +3193,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) { @@ -3015,20 +3234,22 @@ yylex (void) struct type *context_type = NULL; int last_to_examine, next_to_examine, checkpoint; const struct block *search_block; - int is_quoted_name; + 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; + last_lex_was_structop = last_was_structop; + /* Read the first token and decide what to do. Most of the subsequent code is C++-only; but also depends on seeing a "::" or name-like token. */ current.token = lex_one_token (pstate, &is_quoted_name); if (current.token == NAME) - current.token = classify_name (pstate, expression_context_block, - is_quoted_name); - if (parse_language (pstate)->la_language != language_cplus + current.token = classify_name (pstate, pstate->expression_context_block, + is_quoted_name, last_lex_was_structop); + if (pstate->language ()->la_language != language_cplus || (current.token != TYPENAME && current.token != COLONCOLON && current.token != FILENAME)) return current.token; @@ -3036,17 +3257,17 @@ 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) { - int ignore; + bool ignore; /* We ignore quoted names other than the very first one. 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)) @@ -3057,13 +3278,13 @@ 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; - obstack_free (&name_obstack, obstack_base (&name_obstack)); + name_obstack.clear (); checkpoint = 0; if (current.token == FILENAME) search_block = current.value.bval; @@ -3072,7 +3293,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; @@ -3084,16 +3305,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 @@ -3110,8 +3331,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); @@ -3125,7 +3346,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 { @@ -3139,18 +3360,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; } @@ -3158,48 +3380,40 @@ 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; - back_to = make_cleanup (free_current_contents, &expression_macro_scope); - make_cleanup_clear_parser_state (&pstate); + c_parse_state cstate; + scoped_restore cstate_restore = make_scoped_restore (&cpstate, &cstate); - /* Set up the scope for macro expansion. */ - expression_macro_scope = NULL; + gdb::unique_xmalloc_ptr macro_scope; - 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 ()); - make_cleanup_restore_integer (&yydebug); - yydebug = parser_debug; + scoped_restore restore_yydebug = make_scoped_restore (&yydebug, + parser_debug); /* Initialize some state used by the lexer. */ - last_was_structop = 0; + last_was_structop = false; saw_name_at_eof = 0; + paren_depth = 0; - VEC_free (token_and_value, token_fifo); + token_fifo.clear (); popping = 0; - obstack_init (&name_obstack); - make_cleanup_obstack_free (&name_obstack); - - result = yyparse (); - do_cleanups (back_to); + name_obstack.clear (); - return result; + return yyparse (); } #ifdef YYBISON @@ -3231,14 +3445,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: @@ -3246,9 +3460,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; @@ -3260,11 +3474,11 @@ c_print_token (FILE *file, int type, YYSTYPE value) #endif -void -yyerror (char *msg) +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); }