X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=de29d2f70e239efe9437ef5b103ecaf16c18955d;hb=e05523bd2411bac0277da73556f4d01f6c7448aa;hp=e6d6c208f159beb87b9c336a57d52913299603b5;hpb=1e58a4a4db997cf09315c22f3da725d1da7f9ee7;p=binutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index e6d6c208f15..de29d2f70e2 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-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -53,6 +53,9 @@ #include "objc-lang.h" #include "typeprint.h" #include "cp-abi.h" +#include "type-stack.h" +#include "target-float.h" +#include "c-exp.h" #define parse_type(ps) builtin_type (ps->gdbarch ()) @@ -104,6 +107,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. */ @@ -118,6 +124,7 @@ static void yyerror (const char *); static int type_aggregate_p (struct type *); +using namespace expr; %} /* Although the yacc "value" of an expression is not used, @@ -159,10 +166,8 @@ static int parse_number (struct parser_state *par_state, static struct stoken operator_stoken (const char *); 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); -#ifdef YYBISON +#if defined(YYBISON) && YYBISON < 30800 static void c_print_token (FILE *file, int type, YYSTYPE value); #define YYPRINT(FILE, TYPE, VALUE) c_print_token (FILE, TYPE, VALUE) #endif @@ -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 @@ -275,190 +282,213 @@ start : exp1 ; type_exp: type - { write_exp_elt_opcode(pstate, OP_TYPE); - write_exp_elt_type(pstate, $1); - write_exp_elt_opcode(pstate, OP_TYPE);} + { + pstate->push_new ($1); + } | TYPEOF '(' exp ')' { - write_exp_elt_opcode (pstate, OP_TYPEOF); + pstate->wrap (); } | TYPEOF '(' type ')' { - write_exp_elt_opcode (pstate, OP_TYPE); - write_exp_elt_type (pstate, $3); - write_exp_elt_opcode (pstate, OP_TYPE); + pstate->push_new ($3); } | DECLTYPE '(' exp ')' { - write_exp_elt_opcode (pstate, OP_DECLTYPE); + pstate->wrap (); } ; /* Expressions, including the comma operator. */ exp1 : exp | exp1 ',' exp - { write_exp_elt_opcode (pstate, BINOP_COMMA); } + { pstate->wrap2 (); } ; /* Expressions, not including the comma operator. */ exp : '*' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_IND); } + { pstate->wrap (); } ; exp : '&' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_ADDR); } + { pstate->wrap (); } ; exp : '-' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_NEG); } + { pstate->wrap (); } ; exp : '+' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_PLUS); } + { pstate->wrap (); } ; exp : '!' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_LOGICAL_NOT); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap (); + else + pstate->wrap (); + } ; exp : '~' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_COMPLEMENT); } + { pstate->wrap (); } ; exp : INCREMENT exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_PREINCREMENT); } + { pstate->wrap (); } ; exp : DECREMENT exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_PREDECREMENT); } + { pstate->wrap (); } ; exp : exp INCREMENT %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_POSTINCREMENT); } + { pstate->wrap (); } ; exp : exp DECREMENT %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_POSTDECREMENT); } + { pstate->wrap (); } ; exp : TYPEID '(' exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, OP_TYPEID); } + { pstate->wrap (); } ; exp : TYPEID '(' type_exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, OP_TYPEID); } + { pstate->wrap (); } ; exp : SIZEOF exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_SIZEOF); } + { pstate->wrap (); } ; exp : ALIGNOF '(' type_exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_ALIGNOF); } + { pstate->wrap (); } ; exp : exp ARROW field_name - { write_exp_elt_opcode (pstate, STRUCTOP_PTR); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + { + pstate->push_new + (pstate->pop (), copy_name ($3)); + } ; exp : exp ARROW field_name COMPLETE - { mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + { + structop_base_operation *op + = new structop_ptr_operation (pstate->pop (), + copy_name ($3)); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp ARROW COMPLETE - { struct stoken s; - mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); - s.ptr = ""; - s.length = 0; - write_exp_string (pstate, s); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + { + structop_base_operation *op + = new structop_ptr_operation (pstate->pop (), ""); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp ARROW '~' name - { write_exp_elt_opcode (pstate, STRUCTOP_PTR); - write_destructor_name (pstate, $4); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + { + pstate->push_new + (pstate->pop (), "~" + copy_name ($4)); + } ; exp : exp ARROW '~' name COMPLETE - { mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); - write_destructor_name (pstate, $4); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); } + { + structop_base_operation *op + = new structop_ptr_operation (pstate->pop (), + "~" + copy_name ($4)); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp ARROW qualified_name { /* exp->type::name becomes exp->*(&type::name) */ /* Note: this doesn't work if name is a static member! FIXME */ - write_exp_elt_opcode (pstate, UNOP_ADDR); - write_exp_elt_opcode (pstate, STRUCTOP_MPTR); } + pstate->wrap (); + pstate->wrap2 (); } ; exp : exp ARROW_STAR exp - { write_exp_elt_opcode (pstate, STRUCTOP_MPTR); } + { pstate->wrap2 (); } ; exp : exp '.' field_name - { write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->push_new + (pstate->pop (), copy_name ($3)); + else + pstate->push_new + (pstate->pop (), copy_name ($3)); + } ; exp : exp '.' field_name COMPLETE - { mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + { + structop_base_operation *op + = new structop_operation (pstate->pop (), + copy_name ($3)); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp '.' COMPLETE - { struct stoken s; - mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - s.ptr = ""; - s.length = 0; - write_exp_string (pstate, s); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + { + structop_base_operation *op + = new structop_operation (pstate->pop (), ""); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp '.' '~' name - { write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - write_destructor_name (pstate, $4); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + { + pstate->push_new + (pstate->pop (), "~" + copy_name ($4)); + } ; exp : exp '.' '~' name COMPLETE - { mark_struct_expression (pstate); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - write_destructor_name (pstate, $4); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); } + { + structop_base_operation *op + = new structop_operation (pstate->pop (), + "~" + copy_name ($4)); + pstate->mark_struct_expression (op); + pstate->push (operation_up (op)); + } ; exp : exp '.' qualified_name { /* exp.type::name becomes exp.*(&type::name) */ /* Note: this doesn't work if name is a static member! FIXME */ - write_exp_elt_opcode (pstate, UNOP_ADDR); - write_exp_elt_opcode (pstate, STRUCTOP_MEMBER); } + pstate->wrap (); + pstate->wrap2 (); } ; exp : exp DOT_STAR exp - { write_exp_elt_opcode (pstate, STRUCTOP_MEMBER); } + { pstate->wrap2 (); } ; exp : exp '[' exp1 ']' - { write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); } + { pstate->wrap2 (); } ; exp : exp OBJC_LBRAC exp1 ']' - { write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); } + { pstate->wrap2 (); } ; /* @@ -470,48 +500,36 @@ exp : OBJC_LBRAC TYPENAME { CORE_ADDR theclass; + std::string copy = copy_name ($2.stoken); theclass = lookup_objc_class (pstate->gdbarch (), - copy_name ($2.stoken)); + copy.c_str ()); if (theclass == 0) error (_("%s is not an ObjC Class"), - copy_name ($2.stoken)); - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, - parse_type (pstate)->builtin_int); - write_exp_elt_longcst (pstate, (LONGEST) theclass); - write_exp_elt_opcode (pstate, OP_LONG); + copy.c_str ()); + pstate->push_new + (parse_type (pstate)->builtin_int, + (LONGEST) theclass); start_msglist(); } msglist ']' - { write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - end_msglist (pstate); - write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - } + { end_msglist (pstate); } ; exp : OBJC_LBRAC CLASSNAME { - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, - parse_type (pstate)->builtin_int); - write_exp_elt_longcst (pstate, (LONGEST) $2.theclass); - write_exp_elt_opcode (pstate, OP_LONG); + pstate->push_new + (parse_type (pstate)->builtin_int, + (LONGEST) $2.theclass); start_msglist(); } msglist ']' - { write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - end_msglist (pstate); - write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - } + { end_msglist (pstate); } ; exp : OBJC_LBRAC exp { start_msglist(); } msglist ']' - { write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - end_msglist (pstate); - write_exp_elt_opcode (pstate, OP_OBJC_MSGCALL); - } + { end_msglist (pstate); } ; msglist : name @@ -534,23 +552,24 @@ 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 ()); - write_exp_elt_opcode (pstate, OP_FUNCALL); } + { + std::vector args + = pstate->pop_vector (pstate->end_arglist ()); + pstate->push_new + (pstate->pop (), std::move (args)); + } ; /* This is here to disambiguate with the production for "func()::static_var" further below, which uses function_method_void. */ exp : exp '(' ')' %prec ARROW - { start_arglist (); - write_exp_elt_opcode (pstate, OP_FUNCALL); - write_exp_elt_longcst (pstate, - (LONGEST) end_arglist ()); - write_exp_elt_opcode (pstate, OP_FUNCALL); } + { + pstate->push_new + (pstate->pop (), std::vector ()); + } ; @@ -558,70 +577,58 @@ 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, pstate->expression_context_block); - write_exp_elt_sym (pstate, - NULL); /* Placeholder. */ - write_exp_string (pstate, $1.stoken); - write_exp_elt_opcode (pstate, OP_ADL_FUNC); - - /* This is to save the value of arglist_len - being accumulated by an outer function call. */ - - start_arglist (); + /* This is to save the value of arglist_len + being accumulated by an outer function call. */ + pstate->start_arglist (); } arglist ')' %prec ARROW { - write_exp_elt_opcode (pstate, OP_FUNCALL); - write_exp_elt_longcst (pstate, - (LONGEST) end_arglist ()); - write_exp_elt_opcode (pstate, OP_FUNCALL); + std::vector args + = pstate->pop_vector (pstate->end_arglist ()); + pstate->push_new + (copy_name ($1.stoken), + pstate->expression_context_block, + std::move (args)); } ; 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 { std::vector *type_list = $3; - LONGEST len = type_list->size (); - - write_exp_elt_opcode (pstate, TYPE_INSTANCE); /* Save the const/volatile qualifiers as recorded by the const_or_volatile production's actions. */ - write_exp_elt_longcst (pstate, - follow_type_instance_flags ()); - write_exp_elt_longcst (pstate, len); - 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); + type_instance_flags flags + = (cpstate->type_stack + .follow_type_instance_flags ()); + pstate->push_new + (flags, std::move (*type_list), + pstate->pop ()); } ; 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, 0); - write_exp_elt_longcst (pstate, 0); - write_exp_elt_opcode (pstate, TYPE_INSTANCE); + { + type_instance_flags flags + = (cpstate->type_stack + .follow_type_instance_flags ()); + pstate->push_new + (flags, std::vector (), pstate->pop ()); } ; @@ -638,28 +645,35 @@ function_method_void_or_typelist: function_method 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); + pstate->push_new + (pstate->pop (), copy_name ($3)); } ; rcurly : '}' - { $$ = end_arglist () - 1; } + { $$ = pstate->end_arglist () - 1; } ; exp : lcurly arglist rcurly %prec ARROW - { write_exp_elt_opcode (pstate, OP_ARRAY); - write_exp_elt_longcst (pstate, (LONGEST) 0); - write_exp_elt_longcst (pstate, (LONGEST) $3); - write_exp_elt_opcode (pstate, OP_ARRAY); } + { + std::vector args + = pstate->pop_vector ($3 + 1); + pstate->push_new (0, $3, + std::move (args)); + } ; exp : lcurly type_exp rcurly exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_MEMVAL_TYPE); } + { pstate->wrap2 (); } ; exp : '(' type_exp ')' exp %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_CAST_TYPE); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : '(' exp1 ')' @@ -669,101 +683,195 @@ exp : '(' exp1 ')' /* Binary operators in order of decreasing precedence. */ exp : exp '@' exp - { write_exp_elt_opcode (pstate, BINOP_REPEAT); } + { pstate->wrap2 (); } ; exp : exp '*' exp - { write_exp_elt_opcode (pstate, BINOP_MUL); } + { pstate->wrap2 (); } ; exp : exp '/' exp - { write_exp_elt_opcode (pstate, BINOP_DIV); } + { pstate->wrap2 (); } ; exp : exp '%' exp - { write_exp_elt_opcode (pstate, BINOP_REM); } + { pstate->wrap2 (); } ; exp : exp '+' exp - { write_exp_elt_opcode (pstate, BINOP_ADD); } + { pstate->wrap2 (); } ; exp : exp '-' exp - { write_exp_elt_opcode (pstate, BINOP_SUB); } + { pstate->wrap2 (); } ; exp : exp LSH exp - { write_exp_elt_opcode (pstate, BINOP_LSH); } + { pstate->wrap2 (); } ; exp : exp RSH exp - { write_exp_elt_opcode (pstate, BINOP_RSH); } + { pstate->wrap2 (); } ; exp : exp EQUAL exp - { write_exp_elt_opcode (pstate, BINOP_EQUAL); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp NOTEQUAL exp - { write_exp_elt_opcode (pstate, BINOP_NOTEQUAL); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp LEQ exp - { write_exp_elt_opcode (pstate, BINOP_LEQ); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp GEQ exp - { write_exp_elt_opcode (pstate, BINOP_GEQ); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp '<' exp - { write_exp_elt_opcode (pstate, BINOP_LESS); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp '>' exp - { write_exp_elt_opcode (pstate, BINOP_GTR); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp '&' exp - { write_exp_elt_opcode (pstate, BINOP_BITWISE_AND); } + { pstate->wrap2 (); } ; exp : exp '^' exp - { write_exp_elt_opcode (pstate, BINOP_BITWISE_XOR); } + { pstate->wrap2 (); } ; exp : exp '|' exp - { write_exp_elt_opcode (pstate, BINOP_BITWISE_IOR); } + { pstate->wrap2 (); } ; exp : exp ANDAND exp - { write_exp_elt_opcode (pstate, BINOP_LOGICAL_AND); } + { + if (pstate->language ()->la_language + == language_opencl) + { + operation_up rhs = pstate->pop (); + operation_up lhs = pstate->pop (); + pstate->push_new + (BINOP_LOGICAL_AND, std::move (lhs), + std::move (rhs)); + } + else + pstate->wrap2 (); + } ; exp : exp OROR exp - { write_exp_elt_opcode (pstate, BINOP_LOGICAL_OR); } + { + if (pstate->language ()->la_language + == language_opencl) + { + operation_up rhs = pstate->pop (); + operation_up lhs = pstate->pop (); + pstate->push_new + (BINOP_LOGICAL_OR, std::move (lhs), + std::move (rhs)); + } + else + pstate->wrap2 (); + } ; exp : exp '?' exp ':' exp %prec '?' - { write_exp_elt_opcode (pstate, TERNOP_COND); } + { + operation_up last = pstate->pop (); + operation_up mid = pstate->pop (); + operation_up first = pstate->pop (); + if (pstate->language ()->la_language + == language_opencl) + pstate->push_new + (std::move (first), std::move (mid), + std::move (last)); + else + pstate->push_new + (std::move (first), std::move (mid), + std::move (last)); + } ; exp : exp '=' exp - { write_exp_elt_opcode (pstate, BINOP_ASSIGN); } + { + if (pstate->language ()->la_language + == language_opencl) + pstate->wrap2 (); + else + pstate->wrap2 (); + } ; exp : exp ASSIGN_MODIFY exp - { write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); - write_exp_elt_opcode (pstate, $2); - write_exp_elt_opcode (pstate, - BINOP_ASSIGN_MODIFY); } + { + operation_up rhs = pstate->pop (); + operation_up lhs = pstate->pop (); + pstate->push_new + ($2, std::move (lhs), std::move (rhs)); + } ; exp : INT - { write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, $1.type); - write_exp_elt_longcst (pstate, (LONGEST) ($1.val)); - write_exp_elt_opcode (pstate, OP_LONG); } + { + pstate->push_new + ($1.type, $1.val); + } + ; + +exp : COMPLEX_INT + { + operation_up real + = (make_operation + (TYPE_TARGET_TYPE ($1.type), 0)); + operation_up imag + = (make_operation + (TYPE_TARGET_TYPE ($1.type), $1.val)); + pstate->push_new + (std::move (real), std::move (imag), $1.type); + } ; exp : CHAR @@ -771,7 +879,7 @@ exp : CHAR struct stoken_vector vec; vec.len = 1; vec.tokens = &$1; - write_exp_string_vector (pstate, $1.type, &vec); + pstate->push_c_string ($1.type, &vec); } ; @@ -779,20 +887,44 @@ exp : NAME_OR_INT { YYSTYPE val; parse_number (pstate, $1.stoken.ptr, $1.stoken.length, 0, &val); - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, val.typed_val_int.type); - write_exp_elt_longcst (pstate, - (LONGEST) val.typed_val_int.val); - write_exp_elt_opcode (pstate, OP_LONG); + pstate->push_new + (val.typed_val_int.type, + val.typed_val_int.val); } ; exp : FLOAT - { write_exp_elt_opcode (pstate, OP_FLOAT); - write_exp_elt_type (pstate, $1.type); - write_exp_elt_floatcst (pstate, $1.val); - write_exp_elt_opcode (pstate, OP_FLOAT); } + { + float_data data; + std::copy (std::begin ($1.val), std::end ($1.val), + std::begin (data)); + pstate->push_new ($1.type, data); + } + ; + +exp : COMPLEX_FLOAT + { + struct type *underlying + = TYPE_TARGET_TYPE ($1.type); + + float_data val; + target_float_from_host_double (val.data (), + underlying, 0); + operation_up real + = (make_operation + (underlying, val)); + + std::copy (std::begin ($1.val), std::end ($1.val), + std::begin (val)); + operation_up imag + = (make_operation + (underlying, val)); + + pstate->push_new + (std::move (real), std::move (imag), + $1.type); + } ; exp : variable @@ -800,24 +932,22 @@ exp : variable exp : DOLLAR_VARIABLE { - write_dollar_variable (pstate, $1); + pstate->push_dollar ($1); } ; exp : SELECTOR '(' name ')' { - write_exp_elt_opcode (pstate, OP_OBJC_SELECTOR); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, OP_OBJC_SELECTOR); } + pstate->push_new + (copy_name ($3)); + } ; exp : SIZEOF '(' type ')' %prec UNARY { struct type *type = $3; - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, lookup_signed_typename - (pstate->language (), - pstate->gdbarch (), - "int")); + struct type *int_type + = lookup_signed_typename (pstate->language (), + "int"); type = check_typedef (type); /* $5.3.3/2 of the C++ Standard (n3290 draft) @@ -826,28 +956,27 @@ exp : SIZEOF '(' type ')' %prec UNARY the referenced type." */ if (TYPE_IS_REFERENCE (type)) type = check_typedef (TYPE_TARGET_TYPE (type)); - write_exp_elt_longcst (pstate, - (LONGEST) TYPE_LENGTH (type)); - write_exp_elt_opcode (pstate, OP_LONG); } + pstate->push_new + (int_type, TYPE_LENGTH (type)); + } ; exp : REINTERPRET_CAST '<' type_exp '>' '(' exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, - UNOP_REINTERPRET_CAST); } + { pstate->wrap2 (); } ; exp : STATIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_CAST_TYPE); } + { pstate->wrap2 (); } ; exp : DYNAMIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY - { write_exp_elt_opcode (pstate, UNOP_DYNAMIC_CAST); } + { pstate->wrap2 (); } ; exp : CONST_CAST '<' type_exp '>' '(' exp ')' %prec UNARY { /* We could do more error checking here, but it doesn't seem worthwhile. */ - write_exp_elt_opcode (pstate, UNOP_CAST_TYPE); } + pstate->wrap2 (); } ; string_exp: @@ -912,7 +1041,7 @@ exp : string_exp } } - write_exp_string_vector (pstate, type, &$1); + pstate->push_c_string (type, &$1); for (i = 0; i < $1.len; ++i) free ($1.tokens[i].ptr); free ($1.tokens); @@ -922,26 +1051,23 @@ exp : string_exp exp : NSSTRING /* ObjC NextStep NSString constant * of the form '@' '"' string '"'. */ - { write_exp_elt_opcode (pstate, OP_OBJC_NSSTRING); - write_exp_string (pstate, $1); - write_exp_elt_opcode (pstate, OP_OBJC_NSSTRING); } + { + pstate->push_new + (copy_name ($1)); + } ; /* C++. */ exp : TRUEKEYWORD - { write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, - parse_type (pstate)->builtin_bool); - write_exp_elt_longcst (pstate, (LONGEST) 1); - write_exp_elt_opcode (pstate, OP_LONG); } + { pstate->push_new + (parse_type (pstate)->builtin_bool, 1); + } ; exp : FALSEKEYWORD - { write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, - parse_type (pstate)->builtin_bool); - write_exp_elt_longcst (pstate, (LONGEST) 0); - write_exp_elt_opcode (pstate, OP_LONG); } + { pstate->push_new + (parse_type (pstate)->builtin_bool, 0); + } ; /* end of C++. */ @@ -952,7 +1078,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,47 +1087,46 @@ 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) + if (!tem || tem->aclass () != LOC_BLOCK) error (_("No function \"%s\" in specified context."), - copy_name ($3)); + copy.c_str ()); $$ = SYMBOL_BLOCK_VALUE (tem); } ; variable: name_not_typename ENTRY { struct symbol *sym = $1.sym.symbol; - if (sym == NULL || !SYMBOL_IS_ARGUMENT (sym) + if (sym == NULL || !sym->is_argument () || !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); - write_exp_elt_opcode (pstate, OP_VAR_ENTRY_VALUE); + pstate->push_new (sym); } ; 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)) + pstate->block_tracker->update (sym); - innermost_block.update (sym); - - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, sym.block); - write_exp_elt_sym (pstate, sym.symbol); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); } + pstate->push_new (sym); + } ; qualified_name: TYPENAME COLONCOLON name @@ -1012,70 +1137,43 @@ qualified_name: TYPENAME COLONCOLON name error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); - write_exp_elt_opcode (pstate, OP_SCOPE); - write_exp_elt_type (pstate, type); - write_exp_string (pstate, $3); - write_exp_elt_opcode (pstate, OP_SCOPE); + pstate->push_new (type, + copy_name ($3)); } | TYPENAME COLONCOLON '~' name { struct type *type = $1.type; - struct stoken tmp_token; - char *buf; type = check_typedef (type); if (!type_aggregate_p (type)) error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); - buf = (char *) alloca ($4.length + 2); - tmp_token.ptr = buf; - tmp_token.length = $4.length + 1; - buf[0] = '~'; - memcpy (buf+1, $4.ptr, $4.length); - buf[tmp_token.length] = 0; + std::string name = "~" + std::string ($4.ptr, + $4.length); /* Check for valid destructor name. */ - destructor_name_p (tmp_token.ptr, $1.type); - write_exp_elt_opcode (pstate, OP_SCOPE); - write_exp_elt_type (pstate, type); - write_exp_string (pstate, tmp_token); - write_exp_elt_opcode (pstate, OP_SCOPE); + destructor_name_p (name.c_str (), $1.type); + pstate->push_new (type, + std::move (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); - struct symbol *sym; - struct bound_minimal_symbol msymbol; - - sym - = lookup_symbol (name, (const struct block *) NULL, - VAR_DOMAIN, NULL).symbol; - if (sym) - { - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, NULL); - write_exp_elt_sym (pstate, sym); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - break; - } - - msymbol = lookup_bound_minimal_symbol (name); - 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); + std::string name = copy_name ($2.stoken); + struct block_symbol sym + = lookup_symbol (name.c_str (), + (const struct block *) NULL, + VAR_DOMAIN, NULL); + pstate->push_symbol (name.c_str (), sym); } ; @@ -1085,7 +1183,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 @@ -1095,40 +1193,35 @@ variable: name_not_typename bound_minimal_symbol resolver = find_gnu_ifunc (sym.symbol); if (resolver.minsym != NULL) - write_exp_msymbol (pstate, resolver); + pstate->push_new + (resolver); else - { - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, sym.block); - write_exp_elt_sym (pstate, sym.symbol); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - } + pstate->push_new (sym); } else if ($1.is_a_field_of_this) { /* C++: it hangs off of `this'. Must - not inadvertently convert from a method call + not inadvertently convert from a method call to data ref. */ - innermost_block.update (sym); - write_exp_elt_opcode (pstate, OP_THIS); - write_exp_elt_opcode (pstate, OP_THIS); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); - write_exp_string (pstate, $1.stoken); - write_exp_elt_opcode (pstate, STRUCTOP_PTR); + pstate->block_tracker->update (sym); + operation_up thisop + = make_operation (); + pstate->push_new + (std::move (thisop), copy_name ($1.stoken)); } 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 @@ -1145,64 +1238,78 @@ variable: name_not_typename : 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); + block_symbol bsym { alias_target, + SYMBOL_BLOCK_VALUE (alias_target) }; + pstate->push_new (bsym); } else - write_exp_msymbol (pstate, msymbol); + pstate->push_new + (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 ()); + } + | '@' UNKNOWN_CPP_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_noopt 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 +1318,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,225 +1377,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 +scalar_type: + INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int"); } | LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SHORT { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SIGNED_KEYWORD LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | UNSIGNED LONG INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SIGNED_KEYWORD LONG LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SIGNED_KEYWORD LONG LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | UNSIGNED LONG LONG { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | UNSIGNED LONG LONG INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SHORT INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | UNSIGNED SHORT INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | DOUBLE_KEYWORD { $$ = lookup_typename (pstate->language (), - pstate->gdbarch (), "double", NULL, 0); } + | FLOAT_KEYWORD + { $$ = lookup_typename (pstate->language (), + "float", + NULL, + 0); } | LONG DOUBLE_KEYWORD { $$ = lookup_typename (pstate->language (), - pstate->gdbarch (), "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), + = 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), pstate->expression_context_block); + (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), + = 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), + { $$ = 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 (pstate->language (), - pstate->gdbarch (), - TYPE_NAME($2.type)); } - | UNSIGNED - { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), - "int"); } - | SIGNED_KEYWORD type_name - { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), - TYPE_NAME($2.type)); } - | SIGNED_KEYWORD - { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), - "int"); } - /* It appears that this rule for templates is never - reduced; template recognition happens by lookahead - in the token processing code in yylex. */ + /* 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, + (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 @@ -1497,7 +1593,6 @@ type_name: TYPENAME $$.stoken.ptr = "int"; $$.stoken.length = 3; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int"); } | LONG @@ -1505,7 +1600,6 @@ type_name: TYPENAME $$.stoken.ptr = "long"; $$.stoken.length = 4; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SHORT @@ -1513,7 +1607,6 @@ type_name: TYPENAME $$.stoken.ptr = "short"; $$.stoken.length = 5; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } ; @@ -1549,13 +1642,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. */ @@ -1567,13 +1660,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 @@ -1687,17 +1780,18 @@ oper: OPERATOR NEW | OPERATOR OBJC_LBRAC ']' { $$ = operator_stoken ("[]"); } | OPERATOR conversion_type_id - { string_file buf; - + { + string_file buf; c_print_type ($2, NULL, &buf, -1, 0, &type_print_raw_options); + std::string name = buf.release (); /* 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 ()); } ; @@ -1705,12 +1799,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"); } @@ -1753,22 +1846,6 @@ name_not_typename : NAME %% -/* Like write_exp_string, but prepends a '~'. */ - -static void -write_destructor_name (struct parser_state *par_state, struct stoken token) -{ - char *copy = (char *) alloca (token.length + 1); - - copy[0] = '~'; - memcpy (©[1], token.ptr, token.length); - - token.ptr = copy; - ++token.length; - - write_exp_string (par_state, token); -} - /* Returns a stoken of the operator name given by OP (which does not include the string "operator"). */ @@ -1804,11 +1881,11 @@ 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 - && TYPE_DECLARED_CLASS (type))); + return (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION + || type->code () == TYPE_CODE_NAMESPACE + || (type->code () == TYPE_CODE_ENUM + && type->is_declared_class ())); } /* Validate a parameter typelist. */ @@ -1822,7 +1899,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) { @@ -1861,7 +1938,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; @@ -1874,6 +1954,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') { @@ -1916,8 +2002,13 @@ parse_number (struct parser_state *par_state, if (!parse_float (p, len, putithere->typed_val_float.type, putithere->typed_val_float.val)) - return ERROR; - return FLOAT; + return ERROR; + + 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 */ @@ -1966,7 +2057,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') { @@ -1992,6 +2083,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 */ } @@ -2001,13 +2097,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.")); @@ -2079,7 +2175,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. */ @@ -2361,11 +2461,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); @@ -2381,8 +2485,8 @@ static const struct token tokentab3[] = { {">>=", ASSIGN_MODIFY, BINOP_RSH, 0}, {"<<=", ASSIGN_MODIFY, BINOP_LSH, 0}, - {"->*", ARROW_STAR, BINOP_END, FLAG_CXX}, - {"...", DOTDOTDOT, BINOP_END, 0} + {"->*", ARROW_STAR, OP_NULL, FLAG_CXX}, + {"...", DOTDOTDOT, OP_NULL, 0} }; static const struct token tokentab2[] = @@ -2395,27 +2499,27 @@ static const struct token tokentab2[] = {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR, 0}, {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND, 0}, {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR, 0}, - {"++", INCREMENT, BINOP_END, 0}, - {"--", DECREMENT, BINOP_END, 0}, - {"->", ARROW, BINOP_END, 0}, - {"&&", ANDAND, BINOP_END, 0}, - {"||", OROR, BINOP_END, 0}, + {"++", INCREMENT, OP_NULL, 0}, + {"--", DECREMENT, OP_NULL, 0}, + {"->", ARROW, OP_NULL, 0}, + {"&&", ANDAND, OP_NULL, 0}, + {"||", OROR, OP_NULL, 0}, /* "::" is *not* only C++: gdb overrides its meaning in several different ways, e.g., 'filename'::func, function::variable. */ - {"::", COLONCOLON, BINOP_END, 0}, - {"<<", LSH, BINOP_END, 0}, - {">>", RSH, BINOP_END, 0}, - {"==", EQUAL, BINOP_END, 0}, - {"!=", NOTEQUAL, BINOP_END, 0}, - {"<=", LEQ, BINOP_END, 0}, - {">=", GEQ, BINOP_END, 0}, - {".*", DOT_STAR, BINOP_END, FLAG_CXX} + {"::", COLONCOLON, OP_NULL, 0}, + {"<<", LSH, OP_NULL, 0}, + {">>", RSH, OP_NULL, 0}, + {"==", EQUAL, OP_NULL, 0}, + {"!=", NOTEQUAL, OP_NULL, 0}, + {"<=", LEQ, OP_NULL, 0}, + {">=", GEQ, OP_NULL, 0}, + {".*", DOT_STAR, OP_NULL, FLAG_CXX} }; /* 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}, @@ -2427,27 +2531,35 @@ 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}, {"delete", DELETE, OP_NULL, FLAG_CXX}, {"operator", OPERATOR, OP_NULL, FLAG_CXX}, - {"and", ANDAND, BINOP_END, FLAG_CXX}, + {"and", ANDAND, OP_NULL, FLAG_CXX}, {"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, FLAG_CXX}, {"bitand", '&', OP_NULL, FLAG_CXX}, {"bitor", '|', OP_NULL, FLAG_CXX}, {"compl", '~', OP_NULL, FLAG_CXX}, {"not", '!', OP_NULL, FLAG_CXX}, - {"not_eq", NOTEQUAL, BINOP_END, FLAG_CXX}, - {"or", OROR, BINOP_END, FLAG_CXX}, + {"not_eq", NOTEQUAL, OP_NULL, FLAG_CXX}, + {"or", OROR, OP_NULL, FLAG_CXX}, {"or_eq", ASSIGN_MODIFY, BINOP_BITWISE_IOR, FLAG_CXX}, {"xor", '^', OP_NULL, FLAG_CXX}, {"xor_eq", ASSIGN_MODIFY, BINOP_BITWISE_XOR, FLAG_CXX}, @@ -2468,23 +2580,18 @@ static const struct token ident_tokens[] = static void -scan_macro_expansion (char *expansion) +scan_macro_expansion (const char *expansion) { - 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)); - xfree (expansion); + /* Copy to the obstack. */ + const char *copy = obstack_strdup (&cpstate->expansion_obstack, 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 @@ -2500,7 +2607,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; } @@ -2527,6 +2634,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 @@ -2534,10 +2644,8 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) { int c; int namelen; - unsigned int i; const char *tokstart; bool saw_structop = last_was_structop; - char *copy; last_was_structop = false; *is_quoted_name = false; @@ -2547,79 +2655,80 @@ 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, - standard_macro_lookup, - expression_macro_scope); + gdb::unique_xmalloc_ptr expanded + = macro_expand_next (&pstate->lexptr, *expression_macro_scope); - if (expanded) - scan_macro_expansion (expanded); + if (expanded != nullptr) + scan_macro_expansion (expanded.get ()); } - 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) + for (const auto &token : tokentab3) + if (strncmp (tokstart, token.oper, 3) == 0) { - if ((tokentab3[i].flags & FLAG_CXX) != 0 + if ((token.flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((token.flags & FLAG_C) == 0); - lexptr += 3; - yylval.opcode = tokentab3[i].opcode; - return tokentab3[i].token; + pstate->lexptr += 3; + yylval.opcode = token.opcode; + return token.token; } /* See if it is a special token of length 2. */ - for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) - if (strncmp (tokstart, tokentab2[i].oper, 2) == 0) + for (const auto &token : tokentab2) + if (strncmp (tokstart, token.oper, 2) == 0) { - if ((tokentab2[i].flags & FLAG_CXX) != 0 + if ((token.flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((token.flags & FLAG_C) == 0); - lexptr += 2; - yylval.opcode = tokentab2[i].opcode; - if (tokentab2[i].token == ARROW) + pstate->lexptr += 2; + yylval.opcode = token.opcode; + if (token.token == ARROW) last_was_structop = 1; - return tokentab2[i].token; + return token.token; } switch (c = *tokstart) { case 0: /* If we were just scanning the result of a macro expansion, - then we need to resume scanning the original text. + then we need to resume scanning the original text. If we're parsing for field name completion, and the previous token allows such completion, return a COMPLETE token. - Otherwise, we were already scanning the original text, and - we're really done. */ + Otherwise, we were already scanning the original text, and + we're really done. */ if (scanning_macro_expansion ()) - { - finished_macro_expansion (); - goto retry; - } + { + finished_macro_expansion (); + goto retry; + } else if (saw_name_at_eof) { 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; + return 0; case ' ': case '\t': case '\n': - lexptr++; + pstate->lexptr++; goto retry; case '[': case '(': paren_depth++; - lexptr++; + pstate->lexptr++; if (par_state->language ()->la_language == language_objc && c == '[') return OBJC_LBRAC; @@ -2630,20 +2739,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 - && paren_depth == 0 - && ! scanning_macro_expansion ()) + 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. */ @@ -2662,7 +2771,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; @@ -2682,13 +2791,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. */ @@ -2701,8 +2813,8 @@ 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); - if (toktype == ERROR) + got_dot | got_e | got_p, &yylval); + if (toktype == ERROR) { char *err_copy = (char *) alloca (p - tokstart + 1); @@ -2710,7 +2822,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; } @@ -2725,7 +2837,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (strncmp (p, "selector", len) == 0 && (p[len] == '\0' || ISSPACE (p[len]))) { - lexptr = p + len; + pstate->lexptr = p + len; return SELECTOR; } else if (*p == '"') @@ -2738,7 +2850,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; } } @@ -2761,7 +2873,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) case '{': case '}': symbol: - lexptr++; + pstate->lexptr++; return c; case 'L': @@ -2776,8 +2888,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) @@ -2785,7 +2897,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; @@ -2857,7 +2969,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) return 0; } - lexptr += namelen; + pstate->lexptr += namelen; tryname: @@ -2865,23 +2977,27 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) yylval.sval.length = namelen; /* Catch specific keywords. */ - 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) + std::string copy = copy_name (yylval.sval); + for (const auto &token : ident_tokens) + if (copy == token.oper) { - if ((ident_tokens[i].flags & FLAG_CXX) != 0 + if ((token.flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + if ((token.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) + if ((token.flags & FLAG_SHADOW) != 0) { struct field_of_this_result is_a_field_of_this; - if (lookup_symbol (copy, + if (lookup_symbol (copy.c_str (), pstate->expression_context_block, VAR_DOMAIN, (par_state->language ()->la_language - == language_cplus ? &is_a_field_of_this + == language_cplus ? &is_a_field_of_this : NULL)).symbol != NULL) { @@ -2892,14 +3008,14 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) /* It is ok to always set this, even though we don't always strictly need to. */ - yylval.opcode = ident_tokens[i].opcode; - return ident_tokens[i].token; + yylval.opcode = token.opcode; + return token.token; } 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; @@ -2925,7 +3041,7 @@ static int popping; /* Temporary storage for c_lex; this holds symbol names as they are built up. */ -auto_obstack name_obstack; +static 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 @@ -2939,20 +3055,19 @@ 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, - par_state->language ()->la_name_of_this + bsym = lookup_symbol (copy.c_str (), block, VAR_DOMAIN, + par_state->language ()->name_of_this () ? &is_a_field_of_this : NULL); - if (bsym.symbol && SYMBOL_CLASS (bsym.symbol) == LOC_BLOCK) + if (bsym.symbol && bsym.symbol->aclass () == LOC_BLOCK) { yylval.ssym.sym = bsym; yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL; @@ -2971,11 +3086,11 @@ 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) { - yylval.tsym.type = SYMBOL_TYPE (bsym.symbol); + yylval.tsym.type = bsym.symbol->type (); return TYPENAME; } } @@ -2991,35 +3106,36 @@ 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), + yylval.bval = BLOCKVECTOR_BLOCK (symtab->blockvector (), STATIC_BLOCK); return FILENAME; } } } - if (bsym.symbol && SYMBOL_CLASS (bsym.symbol) == LOC_TYPEDEF) + if (bsym.symbol && bsym.symbol->aclass () == LOC_TYPEDEF) { - yylval.tsym.type = SYMBOL_TYPE (bsym.symbol); + yylval.tsym.type = bsym.symbol->type (); return TYPENAME; } /* See if it's an ObjC classname. */ if (par_state->language ()->la_language == language_objc && !bsym.symbol) { - CORE_ADDR Class = lookup_objc_class (par_state->gdbarch (), 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, + sym = lookup_struct_typedef (copy.c_str (), par_state->expression_context_block, 1); if (sym) - yylval.theclass.type = SYMBOL_TYPE (sym); + yylval.theclass.type = sym->type (); return CLASSNAME; } } @@ -3032,7 +3148,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) @@ -3050,7 +3166,7 @@ classify_name (struct parser_state *par_state, const struct block *block, if (bsym.symbol == NULL && 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; @@ -3065,7 +3181,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); @@ -3074,16 +3189,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) { @@ -3094,7 +3211,7 @@ classify_inner_name (struct parser_state *par_state, return ERROR; } - switch (SYMBOL_CLASS (yylval.ssym.sym.symbol)) + switch (yylval.ssym.sym.symbol->aclass ()) { case LOC_BLOCK: case LOC_LABEL: @@ -3102,7 +3219,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) { @@ -3113,7 +3231,7 @@ classify_inner_name (struct parser_state *par_state, return ERROR; case LOC_TYPEDEF: - yylval.tsym.type = SYMBOL_TYPE (yylval.ssym.sym.symbol); + yylval.tsym.type = yylval.ssym.sym.symbol->type (); return TYPENAME; default: @@ -3268,9 +3386,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) @@ -3315,15 +3433,20 @@ 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; name_obstack.clear (); - return yyparse (); + int result = yyparse (); + if (!result) + pstate->set_operation (pstate->pop ()); + return result; } -#ifdef YYBISON +#if defined(YYBISON) && YYBISON < 30800 + /* This is called via the YYPRINT macro when parser debugging is enabled. It prints a token's value. */ @@ -3353,13 +3476,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: @@ -3367,9 +3490,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; @@ -3384,8 +3507,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); }