gdb_byte val[16];
struct type *type;
} typed_val_decfloat;
- struct symbol *sym;
struct type *tval;
struct stoken sval;
struct typed_stoken tsval;
int voidval;
struct block *bval;
enum exp_opcode opcode;
- struct internalvar *ivar;
struct stoken_vector svec;
VEC (type_ptr) *tvec;
- int *ivec;
struct type_stack *type_stack;
static int parse_number (char *, int, int, YYSTYPE *);
static struct stoken operator_stoken (const char *);
static void check_parameter_typelist (VEC (type_ptr) *);
+static void write_destructor_name (struct stoken);
+
+static void c_print_token (FILE *file, int type, YYSTYPE value);
+#define YYPRINT(FILE, TYPE, VALUE) c_print_token (FILE, TYPE, VALUE)
%}
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
%token ENTRY
%token TYPEOF
%token DECLTYPE
+%token TYPEID
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
{ write_exp_elt_opcode (UNOP_POSTDECREMENT); }
;
+exp : TYPEID '(' exp ')' %prec UNARY
+ { write_exp_elt_opcode (OP_TYPEID); }
+ ;
+
+exp : TYPEID '(' type_exp ')' %prec UNARY
+ { write_exp_elt_opcode (OP_TYPEID); }
+ ;
+
exp : SIZEOF exp %prec UNARY
{ write_exp_elt_opcode (UNOP_SIZEOF); }
;
write_exp_elt_opcode (STRUCTOP_PTR); }
;
+exp : exp ARROW '~' name
+ { write_exp_elt_opcode (STRUCTOP_PTR);
+ write_destructor_name ($4);
+ write_exp_elt_opcode (STRUCTOP_PTR); }
+ ;
+
+exp : exp ARROW '~' name COMPLETE
+ { mark_struct_expression ();
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_destructor_name ($4);
+ write_exp_elt_opcode (STRUCTOP_PTR); }
+ ;
+
exp : exp ARROW qualified_name
{ /* exp->type::name becomes exp->*(&type::name) */
/* Note: this doesn't work if name is a
write_exp_elt_opcode (STRUCTOP_STRUCT); }
;
+exp : exp '.' '~' name
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_destructor_name ($4);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+exp : exp '.' '~' name COMPLETE
+ { mark_struct_expression ();
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_destructor_name ($4);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
exp : exp '.' qualified_name
{ /* exp.type::name becomes exp.*(&type::name) */
/* Note: this doesn't work if name is a
{
char *name = copy_name ($2.stoken);
struct symbol *sym;
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
sym =
lookup_symbol (name, (const struct block *) NULL,
break;
}
- msymbol = lookup_minimal_symbol (name, NULL, NULL);
- if (msymbol != NULL)
+ msymbol = lookup_bound_minimal_symbol (name);
+ if (msymbol.minsym != NULL)
write_exp_msymbol (msymbol);
else if (!have_full_symbols () && !have_partial_symbols ())
error (_("No symbol table is loaded. Use the \"file\" command."));
}
else
{
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
char *arg = copy_name ($1.stoken);
msymbol =
- lookup_minimal_symbol (arg, NULL, NULL);
- if (msymbol != NULL)
+ lookup_bound_minimal_symbol (arg);
+ if (msymbol.minsym != NULL)
write_exp_msymbol (msymbol);
else if (!have_full_symbols () && !have_partial_symbols ())
error (_("No symbol table is loaded. Use the \"file\" command."));
%%
+/* Like write_exp_string, but prepends a '~'. */
+
+static void
+write_destructor_name (struct stoken token)
+{
+ char *copy = alloca (token.length + 1);
+
+ copy[0] = '~';
+ memcpy (©[1], token.ptr, token.length);
+
+ token.ptr = copy;
+ ++token.length;
+
+ write_exp_string (token);
+}
+
/* Returns a stoken of the operator name given by OP (which does not
include the string "operator"). */
static struct stoken
{"__typeof", TYPEOF, OP_TYPEOF, 0 },
{"typeof", TYPEOF, OP_TYPEOF, FLAG_SHADOW },
{"__decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX },
- {"decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX | FLAG_SHADOW }
+ {"decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX | FLAG_SHADOW },
+
+ {"typeid", TYPEID, OP_TYPEID, FLAG_CXX}
};
/* When we find that lexptr (the global var defined in parse.c) is
if (parse_completion && *lexptr == '\0')
saw_name_at_eof = 1;
+
+ yylval.ssym.stoken = yylval.sval;
+ yylval.ssym.sym = NULL;
+ yylval.ssym.is_a_field_of_this = 0;
return NAME;
}
}
/* 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. */
+ name might have already been seen. CONTEXT is the context type, or
+ NULL if this is the first component of a name. */
static int
-classify_inner_name (const struct block *block, int first_name)
+classify_inner_name (const struct block *block, struct type *context)
{
struct type *type;
char *copy;
- if (first_name)
+ if (context == NULL)
return classify_name (block);
- type = check_typedef (yylval.tsym.type);
+ type = check_typedef (context);
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
return ERROR;
- copy = copy_name (yylval.tsym.stoken);
- yylval.ssym.sym = cp_lookup_nested_symbol (yylval.tsym.type, copy, block);
+ copy = copy_name (yylval.ssym.stoken);
+ yylval.ssym.sym = cp_lookup_nested_symbol (type, copy, block);
if (yylval.ssym.sym == NULL)
return ERROR;
return TYPENAME;
default:
- yylval.ssym.is_a_field_of_this = 0;
return NAME;
}
internal_error (__FILE__, __LINE__, _("not reached"));
yylex (void)
{
token_and_value current;
- int first_was_coloncolon, last_was_coloncolon, first_iter;
+ int first_was_coloncolon, last_was_coloncolon;
+ struct type *context_type = NULL;
+ int last_to_examine, next_to_examine, checkpoint;
+ const struct block *search_block;
if (popping && !VEC_empty (token_and_value, token_fifo))
- {
- token_and_value tv = *VEC_index (token_and_value, token_fifo, 0);
- VEC_ordered_remove (token_and_value, token_fifo, 0);
- yylval = tv.value;
- return tv.token;
- }
+ goto do_pop;
popping = 0;
+ /* Read the first token and decide what to do. Most of the
+ subsequent code is C++-only; but also depends on seeing a "::" or
+ name-like token. */
current.token = lex_one_token ();
if (current.token == NAME)
current.token = classify_name (expression_context_block);
if (parse_language->la_language != language_cplus
- || (current.token != TYPENAME && current.token != COLONCOLON))
+ || (current.token != TYPENAME && current.token != COLONCOLON
+ && current.token != FILENAME))
return current.token;
- first_was_coloncolon = current.token == COLONCOLON;
- last_was_coloncolon = first_was_coloncolon;
- obstack_free (&name_obstack, obstack_base (&name_obstack));
- if (!last_was_coloncolon)
- obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length);
+ /* Read any sequence of alternating "::" and name-like tokens into
+ the token FIFO. */
current.value = yylval;
- first_iter = 1;
+ VEC_safe_push (token_and_value, token_fifo, ¤t);
+ last_was_coloncolon = current.token == COLONCOLON;
while (1)
{
- token_and_value next;
+ current.token = lex_one_token ();
+ current.value = yylval;
+ VEC_safe_push (token_and_value, token_fifo, ¤t);
+
+ if ((last_was_coloncolon && current.token != NAME)
+ || (!last_was_coloncolon && current.token != COLONCOLON))
+ break;
+ last_was_coloncolon = !last_was_coloncolon;
+ }
+ popping = 1;
+
+ /* We always read one extra token, so compute the number of tokens
+ to examine accordingly. */
+ last_to_examine = VEC_length (token_and_value, token_fifo) - 2;
+ next_to_examine = 0;
+
+ current = *VEC_index (token_and_value, token_fifo, next_to_examine);
+ ++next_to_examine;
+
+ obstack_free (&name_obstack, obstack_base (&name_obstack));
+ checkpoint = 0;
+ if (current.token == FILENAME)
+ search_block = current.value.bval;
+ else if (current.token == COLONCOLON)
+ search_block = NULL;
+ else
+ {
+ gdb_assert (current.token == TYPENAME);
+ search_block = expression_context_block;
+ obstack_grow (&name_obstack, current.value.sval.ptr,
+ current.value.sval.length);
+ context_type = current.value.tsym.type;
+ checkpoint = 1;
+ }
+
+ first_was_coloncolon = current.token == COLONCOLON;
+ last_was_coloncolon = first_was_coloncolon;
+
+ while (next_to_examine <= last_to_examine)
+ {
+ token_and_value *next;
- next.token = lex_one_token ();
- next.value = yylval;
+ next = VEC_index (token_and_value, token_fifo, next_to_examine);
+ ++next_to_examine;
- if (next.token == NAME && last_was_coloncolon)
+ if (next->token == NAME && last_was_coloncolon)
{
int classification;
- classification = classify_inner_name (first_was_coloncolon
- ? NULL
- : expression_context_block,
- first_iter);
+ yylval = next->value;
+ classification = classify_inner_name (search_block, context_type);
/* 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 && classification != NAME)
- {
- /* Push the final component and leave the loop. */
- VEC_safe_push (token_and_value, token_fifo, &next);
- break;
- }
+ break;
+
+ /* Accept up to this token. */
+ checkpoint = next_to_examine;
/* Update the partial name we are constructing. */
- if (!first_iter)
+ if (context_type != NULL)
{
/* We don't want to put a leading "::" into the name. */
obstack_grow_str (&name_obstack, "::");
}
- obstack_grow (&name_obstack, next.value.sval.ptr,
- next.value.sval.length);
+ obstack_grow (&name_obstack, next->value.sval.ptr,
+ next->value.sval.length);
yylval.sval.ptr = obstack_base (&name_obstack);
yylval.sval.length = obstack_object_size (&name_obstack);
current.token = classification;
last_was_coloncolon = 0;
+
+ if (classification == NAME)
+ break;
+
+ context_type = yylval.tsym.type;
}
- else if (next.token == COLONCOLON && !last_was_coloncolon)
+ else if (next->token == COLONCOLON && !last_was_coloncolon)
last_was_coloncolon = 1;
else
{
/* We've reached the end of the name. */
- VEC_safe_push (token_and_value, token_fifo, &next);
break;
}
-
- first_iter = 0;
}
- popping = 1;
-
- /* If we ended with a "::", insert it too. */
- if (last_was_coloncolon)
+ /* If we have a replacement token, install it as the first token in
+ the FIFO, and delete the other constituent tokens. */
+ if (checkpoint > 0)
{
- token_and_value cc;
- memset (&cc, 0, sizeof (token_and_value));
- if (first_was_coloncolon && first_iter)
- {
- yylval = cc.value;
- return COLONCOLON;
- }
- cc.token = COLONCOLON;
- VEC_safe_insert (token_and_value, token_fifo, 0, &cc);
+ current.value.sval.ptr = obstack_copy0 (&expansion_obstack,
+ current.value.sval.ptr,
+ current.value.sval.length);
+
+ VEC_replace (token_and_value, token_fifo, 0, ¤t);
+ if (checkpoint > 1)
+ VEC_block_remove (token_and_value, token_fifo, 1, checkpoint - 1);
}
+ do_pop:
+ current = *VEC_index (token_and_value, token_fifo, 0);
+ VEC_ordered_remove (token_and_value, token_fifo, 0);
yylval = current.value;
- yylval.sval.ptr = obstack_copy0 (&expansion_obstack,
- yylval.sval.ptr,
- yylval.sval.length);
return current.token;
}
return result;
}
+/* This is called via the YYPRINT macro when parser debugging is
+ enabled. It prints a token's value. */
+
+static void
+c_print_token (FILE *file, int type, YYSTYPE value)
+{
+ switch (type)
+ {
+ case INT:
+ fprintf (file, "typed_val_int<%s, %s>",
+ TYPE_SAFE_NAME (value.typed_val_int.type),
+ pulongest (value.typed_val_int.val));
+ break;
+
+ case CHAR:
+ case STRING:
+ {
+ char *copy = alloca (value.tsval.length + 1);
+
+ memcpy (copy, value.tsval.ptr, value.tsval.length);
+ copy[value.tsval.length] = '\0';
+
+ fprintf (file, "tsval<type=%d, %s>", value.tsval.type, copy);
+ }
+ break;
+
+ case NSSTRING:
+ case VARIABLE:
+ fprintf (file, "sval<%s>", copy_name (value.sval));
+ break;
+
+ case TYPENAME:
+ fprintf (file, "tsym<type=%s, name=%s>",
+ TYPE_SAFE_NAME (value.tsym.type),
+ copy_name (value.tsym.stoken));
+ break;
+
+ case NAME:
+ case UNKNOWN_CPP_NAME:
+ case NAME_OR_INT:
+ case BLOCKNAME:
+ fprintf (file, "ssym<name=%s, sym=%s, field_of_this=%d>",
+ copy_name (value.ssym.stoken),
+ (value.ssym.sym == NULL
+ ? "(null)" : SYMBOL_PRINT_NAME (value.ssym.sym)),
+ value.ssym.is_a_field_of_this);
+ break;
+
+ case FILENAME:
+ fprintf (file, "bval<%s>", host_address_to_string (value.bval));
+ break;
+ }
+}
void
yyerror (char *msg)