X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=5ec84eb8ed7abcd09287c2aaab10a53f5095a44e;hb=a350efd4fb368a35ada608f6bc26ccd3bed0ae6b;hp=22768473a83d9b47089f7e6aa4d2f77fb053aeba;hpb=582942f4560f1c8d2a60c2557267f9d3ad8dd6aa;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 22768473a8..5ec84eb8ed 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-2019 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -53,8 +53,10 @@ #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). */ @@ -104,6 +106,9 @@ struct c_parse_state 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. */ @@ -170,7 +175,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %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 */ @@ -181,8 +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 INT COMPLEX_INT +%token FLOAT COMPLEX_FLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -233,6 +238,8 @@ 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 DOLLAR_VARIABLE @@ -364,7 +371,7 @@ exp : exp ARROW field_name ; exp : exp ARROW field_name COMPLETE - { mark_struct_expression (pstate); + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_PTR); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_PTR); } @@ -372,7 +379,7 @@ exp : exp ARROW field_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; @@ -387,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); } @@ -412,7 +419,7 @@ exp : exp '.' field_name ; exp : exp '.' field_name COMPLETE - { mark_struct_expression (pstate); + { pstate->mark_struct_expression (); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); write_exp_string (pstate, $3); write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } @@ -420,7 +427,7 @@ exp : exp '.' field_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; @@ -435,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); } @@ -470,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(); @@ -534,11 +542,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); } ; @@ -546,10 +554,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); } ; @@ -559,8 +567,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); @@ -569,30 +577,30 @@ 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 @@ -604,8 +612,10 @@ function_method: exp '(' parameter_typelist ')' const_or_volatile /* 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 (type *type_elt : *type_list) write_exp_elt_type (pstate, type_elt); @@ -617,8 +627,9 @@ function_method: exp '(' parameter_typelist ')' const_or_volatile 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); @@ -645,7 +656,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); @@ -766,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; @@ -795,6 +822,27 @@ exp : FLOAT write_exp_elt_opcode (pstate, OP_FLOAT); } ; +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_opcode (pstate, OP_COMPLEX); + } + ; + exp : variable ; @@ -815,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); @@ -952,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 { @@ -961,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); } ; @@ -978,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); @@ -987,16 +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)) - - innermost_block.update (sym); + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); @@ -1043,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) { @@ -1069,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 ()); } ; @@ -1085,7 +1137,7 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) - innermost_block.update (sym); + pstate->block_tracker->update (sym); /* If we found a function, see if it's an ifunc resolver that has the same @@ -1109,7 +1161,7 @@ variable: name_not_typename /* 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); @@ -1118,17 +1170,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 @@ -1157,52 +1209,62 @@ variable: name_not_typename } ; -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 - { 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 (); + $$ = 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 ; @@ -1211,31 +1273,31 @@ 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 ($$); } ; @@ -1270,218 +1332,214 @@ func_mod: '(' ')' type : ptype ; -/* Implements (approximately): (type-qualifier)* type-specifier. +/* A helper production that recognizes scalar types that can validly + be used with _Complex. */ - 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), +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", 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", 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 @@ -1489,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"); } ; @@ -1542,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. */ @@ -1560,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 @@ -1684,13 +1739,14 @@ oper: OPERATOR NEW c_print_type ($2, NULL, &buf, -1, 0, &type_print_raw_options); + std::string name = std::move (buf.string ()); /* This also needs canonicalization. */ - std::string canon - = cp_canonicalize_string (buf.c_str ()); - if (canon.empty ()) - canon = std::move (buf.string ()); - $$ = operator_stoken ((" " + canon).c_str ()); + gdb::unique_xmalloc_ptr canon + = cp_canonicalize_string (name.c_str ()); + if (canon != nullptr) + name = canon.get (); + $$ = operator_stoken ((" " + name).c_str ()); } ; @@ -1698,12 +1754,11 @@ oper: OPERATOR NEW 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.*/ + '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"); } @@ -1733,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; } @@ -1796,10 +1852,10 @@ typename_stoken (const char *type) 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))); } @@ -1814,7 +1870,7 @@ check_parameter_typelist (std::vector *params) for (ix = 0; ix < params->size (); ++ix) { type = (*params)[ix]; - if (type != NULL && TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) + if (type != NULL && check_typedef (type)->code () == TYPE_CODE_VOID) { if (ix == 0) { @@ -1853,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; @@ -1866,6 +1925,12 @@ parse_number (struct parser_state *par_state, if (parsed_float) { + 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') { @@ -1909,7 +1974,12 @@ parse_number (struct parser_state *par_state, putithere->typed_val_float.type, putithere->typed_val_float.val)) 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 */ @@ -1958,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') { @@ -1984,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 */ } @@ -1993,13 +2068,13 @@ 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 && prevn >= n) error (_("Numeric constant too large.")); @@ -2021,10 +2096,10 @@ parse_number (struct parser_state *par_state, 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, @@ -2036,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; } @@ -2047,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; @@ -2071,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. */ @@ -2353,11 +2432,15 @@ 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); @@ -2407,7 +2490,7 @@ static const struct token tokentab2[] = /* 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. */ + single word (like 'char') are handled by the classify_name function. */ static const struct token ident_tokens[] = { {"unsigned", UNSIGNED, OP_NULL, 0}, @@ -2419,13 +2502,21 @@ static const struct token ident_tokens[] = {"_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}, @@ -2462,21 +2553,20 @@ static const struct token ident_tokens[] = 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 (! cpstate->macro_original_text); /* Copy to the obstack, and then free the intermediate expansion. */ - copy = (char *) obstack_copy0 (&cpstate->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. */ - cpstate->macro_original_text = lexptr; - lexptr = copy; + cpstate->macro_original_text = pstate->lexptr; + pstate->lexptr = copy; } static int @@ -2492,7 +2582,7 @@ finished_macro_expansion (void) gdb_assert (cpstate->macro_original_text); /* Pop back to the original text. */ - lexptr = cpstate->macro_original_text; + pstate->lexptr = cpstate->macro_original_text; cpstate->macro_original_text = 0; } @@ -2519,6 +2609,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 @@ -2529,7 +2622,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; @@ -2539,7 +2631,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); @@ -2547,18 +2639,19 @@ 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; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); - lexptr += 3; + pstate->lexptr += 3; yylval.opcode = tokentab3[i].opcode; return tokentab3[i].token; } @@ -2568,10 +2661,11 @@ 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; + gdb_assert ((tokentab2[i].flags & FLAG_C) == 0); - lexptr += 2; + pstate->lexptr += 2; yylval.opcode = tokentab2[i].opcode; if (tokentab2[i].token == ARROW) last_was_structop = 1; @@ -2597,7 +2691,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; @@ -2605,14 +2699,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; @@ -2622,20 +2716,20 @@ 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. */ @@ -2654,7 +2748,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) case '9': { /* It's a number. */ - int got_dot = 0, got_e = 0, toktype; + int got_dot = 0, got_e = 0, got_p = 0, toktype; const char *p = tokstart; int hex = input_radix > 10; @@ -2674,13 +2768,16 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) /* This test includes !hex because 'e' is a valid hex digit and thus does not indicate a floating point number when the radix is hex. */ - if (!hex && !got_e && (*p == 'e' || *p == 'E')) + if (!hex && !got_e && !got_p && (*p == 'e' || *p == 'E')) got_dot = got_e = 1; + else if (!got_e && !got_p && (*p == 'p' || *p == 'P')) + got_dot = got_p = 1; /* This test does not include !hex, because a '.' always indicates a decimal floating point number regardless of the radix. */ else if (!got_dot && *p == '.') got_dot = 1; - else if (got_e && (p[-1] == 'e' || p[-1] == 'E') + else if (((got_e && (p[-1] == 'e' || p[-1] == 'E')) + || (got_p && (p[-1] == 'p' || p[-1] == 'P'))) && (*p == '-' || *p == '+')) /* This is the sign of the exponent, not the end of the number. */ @@ -2693,7 +2790,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) break; } toktype = parse_number (par_state, tokstart, p - tokstart, - got_dot|got_e, &yylval); + got_dot | got_e | got_p, &yylval); if (toktype == ERROR) { char *err_copy = (char *) alloca (p - tokstart + 1); @@ -2702,7 +2799,7 @@ 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; } @@ -2710,14 +2807,14 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) { const char *p = &tokstart[1]; - 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]))) { - lexptr = p + len; + pstate->lexptr = p + len; return SELECTOR; } else if (*p == '"') @@ -2730,7 +2827,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len]) && p[len] != '_') { - lexptr = &p[len]; + pstate->lexptr = &p[len]; return ENTRY; } } @@ -2753,7 +2850,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) case '{': case '}': symbol: - lexptr++; + pstate->lexptr++; return c; case 'L': @@ -2768,8 +2865,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) @@ -2777,7 +2874,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; @@ -2849,7 +2946,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) return 0; } - lexptr += namelen; + pstate->lexptr += namelen; tryname: @@ -2857,21 +2954,26 @@ 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_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) @@ -2890,7 +2992,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (*tokstart == '$') 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; @@ -2930,17 +3032,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) @@ -2962,7 +3063,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) { @@ -2982,7 +3083,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), @@ -2999,15 +3100,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; @@ -3022,7 +3125,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) @@ -3038,9 +3141,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; @@ -3055,7 +3158,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); @@ -3064,16 +3166,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) { @@ -3092,7 +3196,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) { @@ -3145,9 +3250,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; @@ -3191,7 +3296,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; @@ -3258,9 +3363,9 @@ yylex (void) if (checkpoint > 0) { current.value.sval.ptr - = (const char *) obstack_copy0 (&cpstate->expansion_obstack, - current.value.sval.ptr, - current.value.sval.length); + = obstack_strndup (&cpstate->expansion_obstack, + current.value.sval.ptr, + current.value.sval.length); token_fifo[0] = current; if (checkpoint > 1) @@ -3288,8 +3393,9 @@ c_parse (struct parser_state *par_state) gdb::unique_xmalloc_ptr macro_scope; - if (expression_context_block) - 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 macro_scope = default_macro_scope (); if (! macro_scope) @@ -3304,6 +3410,7 @@ 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; token_fifo.clear (); popping = 0; @@ -3342,13 +3449,13 @@ c_print_token (FILE *file, int type, YYSTYPE value) case NSSTRING: case DOLLAR_VARIABLE: - parser_fprintf (file, "sval<%s>", copy_name (value.sval)); + 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: @@ -3356,9 +3463,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; @@ -3373,8 +3480,8 @@ c_print_token (FILE *file, int type, YYSTYPE value) 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, lexptr); + error (_("A %s in expression, near `%s'."), msg, pstate->lexptr); }