#include "defs.h"
#include "expression.h"
-#include "parser-defs.h"
#include "value.h"
+#include "parser-defs.h"
#include "language.h"
#include "c-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
%union
{
LONGEST lval;
- unsigned LONGEST ulval;
struct {
LONGEST val;
struct type *type;
block : block COLONCOLON name
{ struct symbol *tem
= lookup_symbol (copy_name ($3), $1,
- VAR_NAMESPACE, 0, NULL);
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
error ("No function \"%s\" in specified context.",
copy_name ($3));
variable: block COLONCOLON name
{ struct symbol *sym;
sym = lookup_symbol (copy_name ($3), $1,
- VAR_NAMESPACE, 0, NULL);
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
if (sym == 0)
error ("No symbol \"%s\" in specified context.",
copy_name ($3));
write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); }
;
struct minimal_symbol *msymbol;
sym =
- lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+ lookup_symbol (name, (const struct block *) NULL,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
if (sym)
{
write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
break;
(struct objfile *) NULL);
if (msymbol != NULL)
{
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_int);
- write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_opcode (UNOP_MEMVAL);
- if (msymbol -> type == mst_data ||
- msymbol -> type == mst_bss)
- write_exp_elt_type (builtin_type_int);
- else if (msymbol -> type == mst_text)
- write_exp_elt_type (lookup_function_type (builtin_type_int));
- else
- write_exp_elt_type (builtin_type_char);
- write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
}
else
if (!have_full_symbols () && !have_partial_symbols ())
if (sym)
{
- switch (SYMBOL_CLASS (sym))
+ if (symbol_read_needs_frame (sym))
{
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM:
- case LOC_LOCAL:
- case LOC_LOCAL_ARG:
if (innermost_block == 0 ||
contained_in (block_found,
innermost_block))
innermost_block = block_found;
- case LOC_UNDEF:
- case LOC_CONST:
- case LOC_STATIC:
- case LOC_TYPEDEF:
- case LOC_LABEL:
- case LOC_BLOCK:
- case LOC_CONST_BYTES:
-
- /* In this case the expression can
- be evaluated regardless of what
- frame we are in, so there is no
- need to check for the
- innermost_block. These cases are
- listed so that gcc -Wall will
- report types that may not have
- been considered. */
-
- break;
}
+
write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
(struct objfile *) NULL);
if (msymbol != NULL)
{
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_int);
- write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
- write_exp_elt_opcode (OP_LONG);
- write_exp_elt_opcode (UNOP_MEMVAL);
- if (msymbol -> type == mst_data ||
- msymbol -> type == mst_bss)
- write_exp_elt_type (builtin_type_int);
- else if (msymbol -> type == mst_text)
- write_exp_elt_type (lookup_function_type (builtin_type_int));
- else
- write_exp_elt_type (builtin_type_char);
- write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
}
else if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
ptype : typebase
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ before the type is currently handled in the typebase rule.
+ The reason for recognizing these here (shift/reduce conflicts)
+ might be obsolete now that some pointer to member rules have
+ been deleted. */
+ | 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: '*'
push_type (tp_array);
$$ = 0;
}
+
| direct_abs_decl func_mod
{ push_type (tp_function); }
| func_mod
{ free ((PTR)$2); $$ = 0; }
;
+/* We used to try to recognize more pointer to member types here, but
+ that didn't work (shift/reduce conflicts meant that these rules never
+ got executed). The problem is that
+ int (foo::bar::baz::bizzle)
+ is a function type but
+ int (foo::bar::baz::bizzle::*)
+ is a pointer to member type. Stroustrup loses again! */
+
type : ptype
| typebase COLONCOLON '*'
{ $$ = lookup_member_type (builtin_type_int, $1); }
- | type '(' typebase COLONCOLON '*' ')'
- { $$ = lookup_member_type ($1, $3); }
- | type '(' typebase COLONCOLON '*' ')' '(' ')'
- { $$ = lookup_member_type
- (lookup_function_type ($1), $3); }
- | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
- { $$ = lookup_member_type
- (lookup_function_type ($1), $3);
- free ((PTR)$8); }
;
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; }
;
{
register LONGEST n = 0;
register LONGEST prevn = 0;
- register int i;
+ register int i = 0;
register int c;
register int base = input_radix;
int unsigned_p = 0;
/* If the number is too big to be an int, or it's got an l suffix
then it's a long. Work out if this has to be a long by
shifting right and and seeing if anything remains, and the
- target int size is different to the target long size. */
-
- if ((TARGET_INT_BIT != TARGET_LONG_BIT && (n >> TARGET_INT_BIT)) || long_p)
+ target int size is different to the target long size.
+
+ In the expression below, we could have tested
+ (n >> TARGET_INT_BIT)
+ to see if it was zero,
+ but too many compilers warn about that, when ints and longs
+ are the same size. So we shift it twice, with fewer bits
+ each time, for the same result. */
+
+ if ( (TARGET_INT_BIT != TARGET_LONG_BIT
+ && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
+ || long_p)
{
high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
unsigned_type = builtin_type_unsigned_long;
if (namelen > 2)
{
lexptr = tokstart + namelen;
+ if (lexptr[-1] != '\'')
+ error ("Unmatched single quote.");
namelen -= 2;
tokstart++;
goto tryname;
for (;; ++p)
{
+ /* 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'))
got_dot = got_e = 1;
- else if (!hex && !got_dot && *p == '.')
+ /* 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')
&& (*p == '-' || *p == '+'))
{ CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
if (lookup_symbol (this_name, expression_context_block,
- VAR_NAMESPACE, 0, NULL))
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL))
return THIS;
}
break;
sym = lookup_symbol (tmp, expression_context_block,
VAR_NAMESPACE,
current_language->la_language == language_cplus
- ? &is_a_field_of_this : NULL,
- NULL);
+ ? &is_a_field_of_this : (int *) NULL,
+ (struct symtab **) NULL);
if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
lookup_partial_symtab (tmp))
{
}
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
- yylval.tsym.type = SYMBOL_TYPE (sym);
+ char *p;
+ char *namestart;
+ struct symbol *best_sym;
+
+ /* Look ahead to detect nested types. This probably should be
+ done in the grammar, but trying seemed to introduce a lot
+ of shift/reduce and reduce/reduce conflicts. It's possible
+ that it could be done, though. Or perhaps a non-grammar, but
+ less ad hoc, approach would work well. */
+
+ /* Since we do not currently have any way of distinguishing
+ a nested type from a non-nested one (the stabs don't tell
+ us whether a type is nested), we just ignore the
+ containing type. */
+
+ p = lexptr;
+ best_sym = sym;
+ while (1)
+ {
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ if (*p == ':' && p[1] == ':')
+ {
+ /* Skip the `::'. */
+ p += 2;
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ namestart = p;
+ while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z'))
+ ++p;
+ if (p != namestart)
+ {
+ struct symbol *cur_sym;
+ /* As big as the whole rest of the expression, which is
+ at least big enough. */
+ char *tmp = alloca (strlen (namestart));
+
+ memcpy (tmp, namestart, p - namestart);
+ tmp[p - namestart] = '\0';
+ cur_sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (cur_sym)
+ {
+ if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
+ {
+ best_sym = cur_sym;
+ lexptr = p;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ yylval.tsym.type = SYMBOL_TYPE (best_sym);
return TYPENAME;
}
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)