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); |