| Index: gdb/c-exp.y
|
| diff --git a/gdb/c-exp.y b/gdb/c-exp.y
|
| index bdcae3310b59b19237e9b0e780f677b1a210f268..0613799c27e27006c2751e5713024193a245b0a6 100644
|
| --- a/gdb/c-exp.y
|
| +++ b/gdb/c-exp.y
|
| @@ -103,6 +103,12 @@
|
| #define yygindex c_yygindex
|
| #define yytable c_yytable
|
| #define yycheck c_yycheck
|
| +#define yyss c_yyss
|
| +#define yysslim c_yysslim
|
| +#define yyssp c_yyssp
|
| +#define yystacksize c_yystacksize
|
| +#define yyvs c_yyvs
|
| +#define yyvsp c_yyvsp
|
|
|
| #ifndef YYDEBUG
|
| #define YYDEBUG 1 /* Default to yydebug support */
|
| @@ -149,26 +155,31 @@ void yyerror (char *);
|
| struct internalvar *ivar;
|
|
|
| struct stoken_vector svec;
|
| - struct type **tvec;
|
| + VEC (type_ptr) *tvec;
|
| int *ivec;
|
| +
|
| + struct type_stack *type_stack;
|
| }
|
|
|
| %{
|
| /* YYSTYPE gets defined by %union */
|
| static int parse_number (char *, int, int, YYSTYPE *);
|
| static struct stoken operator_stoken (const char *);
|
| +static void check_parameter_typelist (VEC (type_ptr) *);
|
| %}
|
|
|
| %type <voidval> exp exp1 type_exp start variable qualified_name lcurly
|
| %type <lval> rcurly
|
| %type <tval> type typebase
|
| -%type <tvec> nonempty_typelist
|
| +%type <tvec> nonempty_typelist func_mod parameter_typelist
|
| /* %type <bval> block */
|
|
|
| /* Fancy type parsing. */
|
| -%type <voidval> func_mod direct_abs_decl abs_decl
|
| %type <tval> ptype
|
| %type <lval> array_mod
|
| +%type <tval> conversion_type_id
|
| +
|
| +%type <type_stack> ptr_operator_ts abs_decl direct_abs_decl
|
|
|
| %token <typed_val_int> INT
|
| %token <typed_val_float> FLOAT
|
| @@ -244,6 +255,8 @@ static struct stoken operator_stoken (const char *);
|
| %type <bval> block
|
| %left COLONCOLON
|
|
|
| +%token DOTDOTDOT
|
| +
|
|
|
| %%
|
|
|
| @@ -430,15 +443,21 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
|
| { arglist_len++; }
|
| ;
|
|
|
| -exp : exp '(' nonempty_typelist ')' const_or_volatile
|
| +exp : exp '(' parameter_typelist ')' const_or_volatile
|
| { int i;
|
| + VEC (type_ptr) *type_list = $3;
|
| + struct type *type_elt;
|
| + LONGEST len = VEC_length (type_ptr, type_list);
|
| +
|
| write_exp_elt_opcode (TYPE_INSTANCE);
|
| - write_exp_elt_longcst ((LONGEST) $<ivec>3[0]);
|
| - for (i = 0; i < $<ivec>3[0]; ++i)
|
| - write_exp_elt_type ($<tvec>3[i + 1]);
|
| - write_exp_elt_longcst((LONGEST) $<ivec>3[0]);
|
| + write_exp_elt_longcst (len);
|
| + for (i = 0;
|
| + VEC_iterate (type_ptr, type_list, i, type_elt);
|
| + ++i)
|
| + write_exp_elt_type (type_elt);
|
| + write_exp_elt_longcst(len);
|
| write_exp_elt_opcode (TYPE_INSTANCE);
|
| - free ($3);
|
| + VEC_free (type_ptr, type_list);
|
| }
|
| ;
|
|
|
| @@ -778,6 +797,13 @@ variable: block COLONCOLON name
|
| if (sym == 0)
|
| error (_("No symbol \"%s\" in specified context."),
|
| copy_name ($3));
|
| + if (symbol_read_needs_frame (sym))
|
| + {
|
| + if (innermost_block == 0
|
| + || contained_in (block_found,
|
| + innermost_block))
|
| + innermost_block = block_found;
|
| + }
|
|
|
| write_exp_elt_opcode (OP_VAR_VALUE);
|
| /* block_found is set by lookup_symbol. */
|
| @@ -918,9 +944,7 @@ variable: name_not_typename
|
| ;
|
|
|
| space_identifier : '@' NAME
|
| - { push_type_address_space (copy_name ($2.stoken));
|
| - push_type (tp_space_identifier);
|
| - }
|
| + { insert_type_address_space (copy_name ($2.stoken)); }
|
| ;
|
|
|
| const_or_volatile: const_or_volatile_noopt
|
| @@ -939,14 +963,31 @@ const_or_volatile_or_space_identifier:
|
| |
|
| ;
|
|
|
| -abs_decl: '*'
|
| - { push_type (tp_pointer); $$ = 0; }
|
| - | '*' abs_decl
|
| - { push_type (tp_pointer); $$ = $2; }
|
| +ptr_operator:
|
| + ptr_operator '*'
|
| + { insert_type (tp_pointer); }
|
| + const_or_volatile_or_space_identifier
|
| + | '*'
|
| + { insert_type (tp_pointer); }
|
| + const_or_volatile_or_space_identifier
|
| | '&'
|
| - { push_type (tp_reference); $$ = 0; }
|
| - | '&' abs_decl
|
| - { push_type (tp_reference); $$ = $2; }
|
| + { insert_type (tp_reference); }
|
| + | '&' ptr_operator
|
| + { insert_type (tp_reference); }
|
| + ;
|
| +
|
| +ptr_operator_ts: ptr_operator
|
| + {
|
| + $$ = get_type_stack ();
|
| + /* This cleanup is eventually run by
|
| + c_parse. */
|
| + make_cleanup (type_stack_cleanup, $$);
|
| + }
|
| + ;
|
| +
|
| +abs_decl: ptr_operator_ts direct_abs_decl
|
| + { $$ = append_type_stack ($2, $1); }
|
| + | ptr_operator_ts
|
| | direct_abs_decl
|
| ;
|
|
|
| @@ -954,20 +995,29 @@ 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 ();
|
| }
|
| | array_mod
|
| {
|
| push_type_int ($1);
|
| push_type (tp_array);
|
| - $$ = 0;
|
| + $$ = get_type_stack ();
|
| }
|
|
|
| | direct_abs_decl func_mod
|
| - { push_type (tp_function); }
|
| + {
|
| + push_type_stack ($1);
|
| + push_typelist ($2);
|
| + $$ = get_type_stack ();
|
| + }
|
| | func_mod
|
| - { push_type (tp_function); }
|
| + {
|
| + push_typelist ($1);
|
| + $$ = get_type_stack ();
|
| + }
|
| ;
|
|
|
| array_mod: '[' ']'
|
| @@ -977,9 +1027,9 @@ array_mod: '[' ']'
|
| ;
|
|
|
| func_mod: '(' ')'
|
| - { $$ = 0; }
|
| - | '(' nonempty_typelist ')'
|
| - { free ($2); $$ = 0; }
|
| + { $$ = NULL; }
|
| + | '(' parameter_typelist ')'
|
| + { $$ = $2; }
|
| ;
|
|
|
| /* We used to try to recognize pointer to member types here, but
|
| @@ -1176,36 +1226,59 @@ typename: TYPENAME
|
| }
|
| ;
|
|
|
| +parameter_typelist:
|
| + nonempty_typelist
|
| + { check_parameter_typelist ($1); }
|
| + | nonempty_typelist ',' DOTDOTDOT
|
| + {
|
| + VEC_safe_push (type_ptr, $1, NULL);
|
| + check_parameter_typelist ($1);
|
| + $$ = $1;
|
| + }
|
| + ;
|
| +
|
| nonempty_typelist
|
| : type
|
| - { $$ = (struct type **) malloc (sizeof (struct type *) * 2);
|
| - $<ivec>$[0] = 1; /* Number of types in vector */
|
| - $$[1] = $1;
|
| + {
|
| + VEC (type_ptr) *typelist = NULL;
|
| + VEC_safe_push (type_ptr, typelist, $1);
|
| + $$ = typelist;
|
| }
|
| | nonempty_typelist ',' type
|
| - { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
|
| - $$ = (struct type **) realloc ((char *) $1, len);
|
| - $$[$<ivec>$[0]] = $3;
|
| + {
|
| + VEC_safe_push (type_ptr, $1, $3);
|
| + $$ = $1;
|
| }
|
| ;
|
|
|
| ptype : typebase
|
| - | ptype const_or_volatile_or_space_identifier abs_decl const_or_volatile_or_space_identifier
|
| + | ptype abs_decl
|
| + {
|
| + push_type_stack ($2);
|
| + $$ = follow_types ($1);
|
| + }
|
| + ;
|
| +
|
| +conversion_type_id: typebase conversion_declarator
|
| { $$ = follow_types ($1); }
|
| ;
|
|
|
| +conversion_declarator: /* Nothing. */
|
| + | ptr_operator conversion_declarator
|
| + ;
|
| +
|
| const_and_volatile: CONST_KEYWORD VOLATILE_KEYWORD
|
| | VOLATILE_KEYWORD CONST_KEYWORD
|
| ;
|
|
|
| const_or_volatile_noopt: const_and_volatile
|
| - { push_type (tp_const);
|
| - push_type (tp_volatile);
|
| + { insert_type (tp_const);
|
| + insert_type (tp_volatile);
|
| }
|
| | CONST_KEYWORD
|
| - { push_type (tp_const); }
|
| + { insert_type (tp_const); }
|
| | VOLATILE_KEYWORD
|
| - { push_type (tp_volatile); }
|
| + { insert_type (tp_volatile); }
|
| ;
|
|
|
| operator: OPERATOR NEW
|
| @@ -1312,7 +1385,7 @@ operator: OPERATOR NEW
|
| { $$ = operator_stoken ("()"); }
|
| | OPERATOR '[' ']'
|
| { $$ = operator_stoken ("[]"); }
|
| - | OPERATOR ptype
|
| + | OPERATOR conversion_type_id
|
| { char *name;
|
| long length;
|
| struct ui_file *buf = mem_fileopen ();
|
| @@ -1374,6 +1447,37 @@ operator_stoken (const char *op)
|
| return st;
|
| };
|
|
|
| +/* Validate a parameter typelist. */
|
| +
|
| +static void
|
| +check_parameter_typelist (VEC (type_ptr) *params)
|
| +{
|
| + struct type *type;
|
| + int ix;
|
| +
|
| + for (ix = 0; VEC_iterate (type_ptr, params, ix, type); ++ix)
|
| + {
|
| + if (type != NULL && TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
|
| + {
|
| + if (ix == 0)
|
| + {
|
| + if (VEC_length (type_ptr, params) == 1)
|
| + {
|
| + /* Ok. */
|
| + break;
|
| + }
|
| + VEC_free (type_ptr, params);
|
| + error (_("parameter types following 'void'"));
|
| + }
|
| + else
|
| + {
|
| + VEC_free (type_ptr, params);
|
| + error (_("'void' invalid as parameter type"));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| /* Take care of parsing a number (anything that starts with a digit).
|
| Set yylval and return the token type; update lexptr.
|
| LEN is the number of characters in it. */
|
| @@ -1406,9 +1510,6 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
|
|
|
| if (parsed_float)
|
| {
|
| - const char *suffix;
|
| - int suffix_len;
|
| -
|
| /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
|
| point. Return DECFLOAT. */
|
|
|
| @@ -1886,7 +1987,8 @@ static const struct token tokentab3[] =
|
| {
|
| {">>=", ASSIGN_MODIFY, BINOP_RSH, 0},
|
| {"<<=", ASSIGN_MODIFY, BINOP_LSH, 0},
|
| - {"->*", ARROW_STAR, BINOP_END, 1}
|
| + {"->*", ARROW_STAR, BINOP_END, 1},
|
| + {"...", DOTDOTDOT, BINOP_END, 0}
|
| };
|
|
|
| static const struct token tokentab2[] =
|
| @@ -2495,9 +2597,8 @@ classify_name (struct block *block)
|
|
|
| /* Like classify_name, but used by the inner loop of the lexer, when a
|
| name might have already been seen. FIRST_NAME is true if the token
|
| - in `yylval' is the first component of a name, false otherwise. If
|
| - this function returns NAME, it might not have updated `yylval'.
|
| - This is ok because the caller only cares about TYPENAME. */
|
| + in `yylval' is the first component of a name, false otherwise. */
|
| +
|
| static int
|
| classify_inner_name (struct block *block, int first_name)
|
| {
|
| @@ -2511,18 +2612,28 @@ classify_inner_name (struct block *block, int first_name)
|
| if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
| && TYPE_CODE (type) != TYPE_CODE_UNION
|
| && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
| - /* We know the caller won't expect us to update yylval. */
|
| - return NAME;
|
| + return ERROR;
|
|
|
| copy = copy_name (yylval.tsym.stoken);
|
| - new_type = cp_lookup_nested_type (yylval.tsym.type, copy, block);
|
| + yylval.ssym.sym = cp_lookup_nested_symbol (yylval.tsym.type, copy, block);
|
| + if (yylval.ssym.sym == NULL)
|
| + return ERROR;
|
|
|
| - if (new_type == NULL)
|
| - /* We know the caller won't expect us to update yylval. */
|
| - return NAME;
|
| + switch (SYMBOL_CLASS (yylval.ssym.sym))
|
| + {
|
| + case LOC_BLOCK:
|
| + case LOC_LABEL:
|
| + return ERROR;
|
|
|
| - yylval.tsym.type = new_type;
|
| - return TYPENAME;
|
| + case LOC_TYPEDEF:
|
| + yylval.tsym.type = SYMBOL_TYPE (yylval.ssym.sym);;
|
| + return TYPENAME;
|
| +
|
| + default:
|
| + yylval.ssym.is_a_field_of_this = 0;
|
| + return NAME;
|
| + }
|
| + internal_error (__FILE__, __LINE__, _("not reached"));
|
| }
|
|
|
| /* The outer level of a two-level lexer. This calls the inner lexer
|
| @@ -2582,7 +2693,7 @@ yylex (void)
|
| first_iter);
|
| /* We keep going until we either run out of names, or until
|
| we have a qualified name which is not a type. */
|
| - if (classification != TYPENAME)
|
| + if (classification != TYPENAME && classification != NAME)
|
| {
|
| /* Push the final component and leave the loop. */
|
| VEC_safe_push (token_and_value, token_fifo, &next);
|
|
|