* parse.c, parser-defs.h (follow_types): New function.
* c-exp.y (ptype : typebase abs_decl): Use it. * c-exp.y (ptype): Add support for type qualifiers after the typebase. The typebase rule already has support for them before the typebase. * Makefile.in: Change the expected number of shift/reduce conflicts to 6. This is OK--the 2 new conflicts are basically the same as one of the old ones.
This commit is contained in:
parent
cf4d863151
commit
f843c95fc3
3 changed files with 73 additions and 41 deletions
65
gdb/c-exp.y
65
gdb/c-exp.y
|
@ -722,48 +722,23 @@ variable: name_not_typename
|
|||
;
|
||||
|
||||
|
||||
/* shift/reduce conflict: "typebase ." and the token is '('. (Shows up
|
||||
twice, once where qualified_name is a possibility and once where
|
||||
it is not). */
|
||||
/* shift/reduce conflict: "typebase CONST_KEYWORD ." and the token is '('. */
|
||||
/* shift/reduce conflict: "typebase VOLATILE_KEYWORD ." and the token is
|
||||
'('. */
|
||||
ptype : typebase
|
||||
/* "const" and "volatile" are curently ignored. A type qualifier
|
||||
before the type is currently handled in the typebase rule. */
|
||||
| typebase CONST_KEYWORD
|
||||
| typebase VOLATILE_KEYWORD
|
||||
| typebase abs_decl
|
||||
{
|
||||
/* This is where the interesting stuff happens. */
|
||||
int done = 0;
|
||||
int array_size;
|
||||
struct type *follow_type = $1;
|
||||
struct type *range_type;
|
||||
|
||||
while (!done)
|
||||
switch (pop_type ())
|
||||
{
|
||||
case tp_end:
|
||||
done = 1;
|
||||
break;
|
||||
case tp_pointer:
|
||||
follow_type = lookup_pointer_type (follow_type);
|
||||
break;
|
||||
case tp_reference:
|
||||
follow_type = lookup_reference_type (follow_type);
|
||||
break;
|
||||
case tp_array:
|
||||
array_size = pop_type_int ();
|
||||
if (array_size != -1)
|
||||
{
|
||||
range_type =
|
||||
create_range_type ((struct type *) NULL,
|
||||
builtin_type_int, 0,
|
||||
array_size - 1);
|
||||
follow_type =
|
||||
create_array_type ((struct type *) NULL,
|
||||
follow_type, range_type);
|
||||
}
|
||||
else
|
||||
follow_type = lookup_pointer_type (follow_type);
|
||||
break;
|
||||
case tp_function:
|
||||
follow_type = lookup_function_type (follow_type);
|
||||
break;
|
||||
}
|
||||
$$ = follow_type;
|
||||
}
|
||||
{ $$ = follow_types ($1); }
|
||||
| typebase CONST_KEYWORD abs_decl
|
||||
{ $$ = follow_types ($1); }
|
||||
| typebase VOLATILE_KEYWORD abs_decl
|
||||
{ $$ = follow_types ($1); }
|
||||
;
|
||||
|
||||
abs_decl: '*'
|
||||
|
@ -790,6 +765,10 @@ direct_abs_decl: '(' abs_decl ')'
|
|||
push_type (tp_array);
|
||||
$$ = 0;
|
||||
}
|
||||
|
||||
/* shift/reduce conflict. "direct_abs_decl . func_mod", and the token
|
||||
is '('. */
|
||||
|
||||
| direct_abs_decl func_mod
|
||||
{ push_type (tp_function); }
|
||||
| func_mod
|
||||
|
@ -808,6 +787,8 @@ func_mod: '(' ')'
|
|||
{ free ((PTR)$2); $$ = 0; }
|
||||
;
|
||||
|
||||
/* shift/reduce conflict: "type '(' typebase COLONCOLON '*' ')' ." and the
|
||||
token is '('. */
|
||||
type : ptype
|
||||
| typebase COLONCOLON '*'
|
||||
{ $$ = lookup_member_type (builtin_type_int, $1); }
|
||||
|
@ -871,7 +852,9 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
|||
{ $$ = lookup_template_type(copy_name($2), $4,
|
||||
expression_context_block);
|
||||
}
|
||||
/* "const" and "volatile" are curently ignored. */
|
||||
/* "const" and "volatile" are curently ignored. A type qualifier
|
||||
after the type is handled in the ptype rule. I think these could
|
||||
be too. */
|
||||
| CONST_KEYWORD typebase { $$ = $2; }
|
||||
| VOLATILE_KEYWORD typebase { $$ = $2; }
|
||||
;
|
||||
|
|
47
gdb/parse.c
47
gdb/parse.c
|
@ -726,6 +726,9 @@ parse_expression (string)
|
|||
error ("Junk after end of expression.");
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Stuff for maintaining a stack of types. Currently just used by C, but
|
||||
probably useful for any language which declares its types "backwards". */
|
||||
|
||||
void
|
||||
push_type (tp)
|
||||
|
@ -770,6 +773,50 @@ pop_type_int ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
|
||||
as modified by all the stuff on the stack. */
|
||||
struct type *
|
||||
follow_types (follow_type)
|
||||
struct type *follow_type;
|
||||
{
|
||||
int done = 0;
|
||||
int array_size;
|
||||
struct type *range_type;
|
||||
|
||||
while (!done)
|
||||
switch (pop_type ())
|
||||
{
|
||||
case tp_end:
|
||||
done = 1;
|
||||
break;
|
||||
case tp_pointer:
|
||||
follow_type = lookup_pointer_type (follow_type);
|
||||
break;
|
||||
case tp_reference:
|
||||
follow_type = lookup_reference_type (follow_type);
|
||||
break;
|
||||
case tp_array:
|
||||
array_size = pop_type_int ();
|
||||
if (array_size != -1)
|
||||
{
|
||||
range_type =
|
||||
create_range_type ((struct type *) NULL,
|
||||
builtin_type_int, 0,
|
||||
array_size - 1);
|
||||
follow_type =
|
||||
create_array_type ((struct type *) NULL,
|
||||
follow_type, range_type);
|
||||
}
|
||||
else
|
||||
follow_type = lookup_pointer_type (follow_type);
|
||||
break;
|
||||
case tp_function:
|
||||
follow_type = lookup_function_type (follow_type);
|
||||
break;
|
||||
}
|
||||
return follow_type;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_parse ()
|
||||
{
|
||||
|
|
|
@ -133,6 +133,8 @@ pop_type PARAMS ((void));
|
|||
extern int
|
||||
pop_type_int PARAMS ((void));
|
||||
|
||||
extern struct type *follow_types PARAMS ((struct type *));
|
||||
|
||||
/* During parsing of a C expression, the pointer to the next character
|
||||
is in this variable. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue