/* YACC parser for C expressions, for GDB.
- Copyright (C) 1986, 1989-2000, 2003-2004, 2006-2012 Free Software
- Foundation, Inc.
+ Copyright (C) 1986-2013 Free Software Foundation, Inc.
This file is part of GDB.
#include "dfp.h"
#include "gdb_assert.h"
#include "macroscope.h"
+#include "objc-lang.h"
+#include "typeprint.h"
+#include "cp-abi.h"
#define parse_type builtin_type (parse_gdbarch)
int *ivec;
struct type_stack *type_stack;
+
+ struct objc_class_str class;
}
%{
nonterminal "name", which matches either NAME or TYPENAME. */
%token <tsval> STRING
+%token <sval> NSSTRING /* ObjC Foundation "NSString" literal */
+%token SELECTOR /* ObjC "@selector" pseudo-operator */
%token <tsval> CHAR
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
%token <ssym> UNKNOWN_CPP_NAME
%token <voidval> COMPLETE
%token <tsym> TYPENAME
+%token <class> CLASSNAME /* ObjC Class name */
%type <sval> name
%type <svec> string_exp
%type <ssym> name_not_typename
%type <tsym> typename
+ /* This is like a '[' token, but is only generated when parsing
+ Objective C. This lets us reuse the same parser without
+ erroneously parsing ObjC-specific expressions in C. */
+%token OBJC_LBRAC
+
/* A NAME_OR_INT is a symbol which is not known in the symbol table,
but which would parse as a valid number in the current input radix.
E.g. "c" when input_radix==16. Depending on the parse, it will be
%type <sval> operator
%token REINTERPRET_CAST DYNAMIC_CAST STATIC_CAST CONST_CAST
%token ENTRY
+%token TYPEOF
+%token DECLTYPE
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
%left '+' '-'
%left '*' '/' '%'
%right UNARY INCREMENT DECREMENT
-%right ARROW ARROW_STAR '.' DOT_STAR '[' '('
+%right ARROW ARROW_STAR '.' DOT_STAR '[' OBJC_LBRAC '('
%token <ssym> BLOCKNAME
%token <bval> FILENAME
%type <bval> block
{ write_exp_elt_opcode(OP_TYPE);
write_exp_elt_type($1);
write_exp_elt_opcode(OP_TYPE);}
+ | TYPEOF '(' exp ')'
+ {
+ write_exp_elt_opcode (OP_TYPEOF);
+ }
+ | TYPEOF '(' type ')'
+ {
+ write_exp_elt_opcode (OP_TYPE);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (OP_TYPE);
+ }
+ | DECLTYPE '(' exp ')'
+ {
+ write_exp_elt_opcode (OP_DECLTYPE);
+ }
;
/* Expressions, including the comma operator. */
{ write_exp_elt_opcode (BINOP_SUBSCRIPT); }
;
+exp : exp OBJC_LBRAC exp1 ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+ ;
+
+/*
+ * The rules below parse ObjC message calls of the form:
+ * '[' target selector {':' argument}* ']'
+ */
+
+exp : OBJC_LBRAC TYPENAME
+ {
+ CORE_ADDR class;
+
+ class = lookup_objc_class (parse_gdbarch,
+ copy_name ($2.stoken));
+ if (class == 0)
+ error (_("%s is not an ObjC Class"),
+ copy_name ($2.stoken));
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (parse_type->builtin_int);
+ write_exp_elt_longcst ((LONGEST) class);
+ write_exp_elt_opcode (OP_LONG);
+ start_msglist();
+ }
+ msglist ']'
+ { write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ end_msglist();
+ write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ }
+ ;
+
+exp : OBJC_LBRAC CLASSNAME
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (parse_type->builtin_int);
+ write_exp_elt_longcst ((LONGEST) $2.class);
+ write_exp_elt_opcode (OP_LONG);
+ start_msglist();
+ }
+ msglist ']'
+ { write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ end_msglist();
+ write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ }
+ ;
+
+exp : OBJC_LBRAC exp
+ { start_msglist(); }
+ msglist ']'
+ { write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ end_msglist();
+ write_exp_elt_opcode (OP_OBJC_MSGCALL);
+ }
+ ;
+
+msglist : name
+ { add_msglist(&$1, 0); }
+ | msgarglist
+ ;
+
+msgarglist : msgarg
+ | msgarglist msgarg
+ ;
+
+msgarg : name ':' exp
+ { add_msglist(&$1, 1); }
+ | ':' exp /* Unnamed arg. */
+ { add_msglist(0, 1); }
+ | ',' exp /* Variable number of args. */
+ { add_msglist(0, 0); }
+ ;
+
exp : exp '('
/* This is to save the value of arglist_len
being accumulated by an outer function call. */
write_exp_elt_opcode (OP_ARRAY); }
;
-exp : lcurly type rcurly exp %prec UNARY
- { write_exp_elt_opcode (UNOP_MEMVAL);
- write_exp_elt_type ($2);
- write_exp_elt_opcode (UNOP_MEMVAL); }
+exp : lcurly type_exp rcurly exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_MEMVAL_TYPE); }
;
-exp : '(' type ')' exp %prec UNARY
- { write_exp_elt_opcode (UNOP_CAST);
- write_exp_elt_type ($2);
- write_exp_elt_opcode (UNOP_CAST); }
+exp : '(' type_exp ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST_TYPE); }
;
exp : '(' exp1 ')'
}
;
+exp : SELECTOR '(' name ')'
+ {
+ write_exp_elt_opcode (OP_OBJC_SELECTOR);
+ write_exp_string ($3);
+ write_exp_elt_opcode (OP_OBJC_SELECTOR); }
+ ;
+
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (lookup_signed_typename
write_exp_elt_opcode (OP_LONG); }
;
-exp : REINTERPRET_CAST '<' type '>' '(' exp ')' %prec UNARY
- { write_exp_elt_opcode (UNOP_REINTERPRET_CAST);
- write_exp_elt_type ($3);
- write_exp_elt_opcode (UNOP_REINTERPRET_CAST); }
+exp : REINTERPRET_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+ { write_exp_elt_opcode (UNOP_REINTERPRET_CAST); }
;
-exp : STATIC_CAST '<' type '>' '(' exp ')' %prec UNARY
- { write_exp_elt_opcode (UNOP_CAST);
- write_exp_elt_type ($3);
- write_exp_elt_opcode (UNOP_CAST); }
+exp : STATIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST_TYPE); }
;
-exp : DYNAMIC_CAST '<' type '>' '(' exp ')' %prec UNARY
- { write_exp_elt_opcode (UNOP_DYNAMIC_CAST);
- write_exp_elt_type ($3);
- write_exp_elt_opcode (UNOP_DYNAMIC_CAST); }
+exp : DYNAMIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+ { write_exp_elt_opcode (UNOP_DYNAMIC_CAST); }
;
-exp : CONST_CAST '<' type '>' '(' exp ')' %prec UNARY
+exp : CONST_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
{ /* We could do more error checking here, but
it doesn't seem worthwhile. */
- write_exp_elt_opcode (UNOP_CAST);
- write_exp_elt_type ($3);
- write_exp_elt_opcode (UNOP_CAST); }
+ write_exp_elt_opcode (UNOP_CAST_TYPE); }
;
string_exp:
}
;
+exp : NSSTRING /* ObjC NextStep NSString constant
+ * of the form '@' '"' string '"'.
+ */
+ { write_exp_elt_opcode (OP_OBJC_NSSTRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_OBJC_NSSTRING); }
+ ;
+
/* C++. */
exp : TRUEKEYWORD
{ write_exp_elt_opcode (OP_LONG);
block : block COLONCOLON name
{ struct symbol *tem
= lookup_symbol (copy_name ($3), $1,
- VAR_DOMAIN, (int *) NULL);
+ VAR_DOMAIN, 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_DOMAIN, (int *) NULL);
+ VAR_DOMAIN, NULL);
if (sym == 0)
error (_("No symbol \"%s\" in specified context."),
copy_name ($3));
sym =
lookup_symbol (name, (const struct block *) NULL,
- VAR_DOMAIN, (int *) NULL);
+ VAR_DOMAIN, NULL);
if (sym)
{
write_exp_elt_opcode (OP_VAR_VALUE);
array_mod: '[' ']'
{ $$ = -1; }
+ | OBJC_LBRAC ']'
+ { $$ = -1; }
| '[' INT ']'
{ $$ = $2.val; }
+ | OBJC_LBRAC INT ']'
+ { $$ = $2.val; }
;
func_mod: '(' ')'
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
+ | STRUCT COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
+ $$ = NULL;
+ }
+ | STRUCT name COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr,
+ $2.length);
+ $$ = NULL;
+ }
| CLASS name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
+ | CLASS COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_CLASS, "", 0);
+ $$ = NULL;
+ }
+ | CLASS name COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_CLASS, $2.ptr,
+ $2.length);
+ $$ = NULL;
+ }
| UNION name
{ $$ = lookup_union (copy_name ($2),
expression_context_block); }
+ | UNION COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_UNION, "", 0);
+ $$ = NULL;
+ }
+ | UNION name COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_UNION, $2.ptr,
+ $2.length);
+ $$ = NULL;
+ }
| ENUM name
{ $$ = lookup_enum (copy_name ($2),
expression_context_block); }
+ | ENUM COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_ENUM, "", 0);
+ $$ = NULL;
+ }
+ | ENUM name COMPLETE
+ {
+ mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
+ $2.length);
+ $$ = NULL;
+ }
| UNSIGNED typename
{ $$ = lookup_unsigned_typename (parse_language,
parse_gdbarch,
{ $$ = operator_stoken (" new[]"); }
| OPERATOR DELETE '[' ']'
{ $$ = operator_stoken (" delete[]"); }
+ | OPERATOR NEW OBJC_LBRAC ']'
+ { $$ = operator_stoken (" new[]"); }
+ | OPERATOR DELETE OBJC_LBRAC ']'
+ { $$ = operator_stoken (" delete[]"); }
| OPERATOR '+'
{ $$ = operator_stoken ("+"); }
| OPERATOR '-'
{ $$ = operator_stoken ("()"); }
| OPERATOR '[' ']'
{ $$ = operator_stoken ("[]"); }
+ | OPERATOR OBJC_LBRAC ']'
+ { $$ = operator_stoken ("[]"); }
| OPERATOR conversion_type_id
{ char *name;
long length;
struct ui_file *buf = mem_fileopen ();
- c_print_type ($2, NULL, buf, -1, 0);
+ c_print_type ($2, NULL, buf, -1, 0,
+ &type_print_raw_options);
name = ui_file_xstrdup (buf, &length);
ui_file_delete (buf);
$$ = operator_stoken (name);
*/
| operator
{
+ struct field_of_this_result is_a_field_of_this;
+
$$.stoken = $1;
$$.sym = lookup_symbol ($1.ptr,
expression_context_block,
VAR_DOMAIN,
- &$$.is_a_field_of_this);
+ &is_a_field_of_this);
+ $$.is_a_field_of_this
+ = is_a_field_of_this.type != NULL;
}
| UNKNOWN_CPP_NAME
;
{
int quote;
enum c_string_type type;
+ int is_objc = 0;
/* Build the gdb internal form of the input string in tempbuf. Note
that the buffer is null byte terminated *only* for the
type = C_STRING_32;
++tokptr;
}
+ else if (*tokptr == '@')
+ {
+ /* An Objective C string. */
+ is_objc = 1;
+ type = C_STRING;
+ ++tokptr;
+ }
else
type = C_STRING;
*outptr = tokptr;
- return quote == '"' ? STRING : CHAR;
+ return quote == '"' ? (is_objc ? NSSTRING : STRING) : CHAR;
}
+/* This is used to associate some attributes with a token. */
+
+enum token_flags
+{
+ /* If this bit is set, the token is C++-only. */
+
+ FLAG_CXX = 1,
+
+ /* If this bit is set, the token is conditional: if there is a
+ symbol of the same name, then the token is a symbol; otherwise,
+ the token is a keyword. */
+
+ FLAG_SHADOW = 2
+};
+
struct token
{
char *operator;
int token;
enum exp_opcode opcode;
- int cxx_only;
+ enum token_flags flags;
};
static const struct token tokentab3[] =
{
{">>=", ASSIGN_MODIFY, BINOP_RSH, 0},
{"<<=", ASSIGN_MODIFY, BINOP_LSH, 0},
- {"->*", ARROW_STAR, BINOP_END, 1},
+ {"->*", ARROW_STAR, BINOP_END, FLAG_CXX},
{"...", DOTDOTDOT, BINOP_END, 0}
};
{"!=", NOTEQUAL, BINOP_END, 0},
{"<=", LEQ, BINOP_END, 0},
{">=", GEQ, BINOP_END, 0},
- {".*", DOT_STAR, BINOP_END, 1}
+ {".*", DOT_STAR, BINOP_END, FLAG_CXX}
};
/* Identifier-like tokens. */
static const struct token ident_tokens[] =
{
{"unsigned", UNSIGNED, OP_NULL, 0},
- {"template", TEMPLATE, OP_NULL, 1},
+ {"template", TEMPLATE, OP_NULL, FLAG_CXX},
{"volatile", VOLATILE_KEYWORD, OP_NULL, 0},
{"struct", STRUCT, OP_NULL, 0},
{"signed", SIGNED_KEYWORD, OP_NULL, 0},
{"sizeof", SIZEOF, OP_NULL, 0},
{"double", DOUBLE_KEYWORD, OP_NULL, 0},
- {"false", FALSEKEYWORD, OP_NULL, 1},
- {"class", CLASS, OP_NULL, 1},
+ {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX},
+ {"class", CLASS, OP_NULL, FLAG_CXX},
{"union", UNION, OP_NULL, 0},
{"short", SHORT, OP_NULL, 0},
{"const", CONST_KEYWORD, OP_NULL, 0},
{"enum", ENUM, OP_NULL, 0},
{"long", LONG, OP_NULL, 0},
- {"true", TRUEKEYWORD, OP_NULL, 1},
+ {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX},
{"int", INT_KEYWORD, OP_NULL, 0},
- {"new", NEW, OP_NULL, 1},
- {"delete", DELETE, OP_NULL, 1},
- {"operator", OPERATOR, OP_NULL, 1},
-
- {"and", ANDAND, BINOP_END, 1},
- {"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, 1},
- {"bitand", '&', OP_NULL, 1},
- {"bitor", '|', OP_NULL, 1},
- {"compl", '~', OP_NULL, 1},
- {"not", '!', OP_NULL, 1},
- {"not_eq", NOTEQUAL, BINOP_END, 1},
- {"or", OROR, BINOP_END, 1},
- {"or_eq", ASSIGN_MODIFY, BINOP_BITWISE_IOR, 1},
- {"xor", '^', OP_NULL, 1},
- {"xor_eq", ASSIGN_MODIFY, BINOP_BITWISE_XOR, 1},
-
- {"const_cast", CONST_CAST, OP_NULL, 1 },
- {"dynamic_cast", DYNAMIC_CAST, OP_NULL, 1 },
- {"static_cast", STATIC_CAST, OP_NULL, 1 },
- {"reinterpret_cast", REINTERPRET_CAST, OP_NULL, 1 }
+ {"new", NEW, OP_NULL, FLAG_CXX},
+ {"delete", DELETE, OP_NULL, FLAG_CXX},
+ {"operator", OPERATOR, OP_NULL, FLAG_CXX},
+
+ {"and", ANDAND, BINOP_END, FLAG_CXX},
+ {"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, FLAG_CXX},
+ {"bitand", '&', OP_NULL, FLAG_CXX},
+ {"bitor", '|', OP_NULL, FLAG_CXX},
+ {"compl", '~', OP_NULL, FLAG_CXX},
+ {"not", '!', OP_NULL, FLAG_CXX},
+ {"not_eq", NOTEQUAL, BINOP_END, FLAG_CXX},
+ {"or", OROR, BINOP_END, FLAG_CXX},
+ {"or_eq", ASSIGN_MODIFY, BINOP_BITWISE_IOR, FLAG_CXX},
+ {"xor", '^', OP_NULL, FLAG_CXX},
+ {"xor_eq", ASSIGN_MODIFY, BINOP_BITWISE_XOR, FLAG_CXX},
+
+ {"const_cast", CONST_CAST, OP_NULL, FLAG_CXX },
+ {"dynamic_cast", DYNAMIC_CAST, OP_NULL, FLAG_CXX },
+ {"static_cast", STATIC_CAST, OP_NULL, FLAG_CXX },
+ {"reinterpret_cast", REINTERPRET_CAST, OP_NULL, FLAG_CXX },
+
+ {"__typeof__", TYPEOF, OP_TYPEOF, 0 },
+ {"__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 }
};
/* When we find that lexptr (the global var defined in parse.c) is
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
{
- if (tokentab3[i].cxx_only
+ if ((tokentab3[i].flags & FLAG_CXX) != 0
&& parse_language->la_language != language_cplus)
break;
for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
{
- if (tokentab2[i].cxx_only
+ if ((tokentab2[i].flags & FLAG_CXX) != 0
&& parse_language->la_language != language_cplus)
break;
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
- if (in_parse_field && tokentab2[i].token == ARROW)
+ if (parse_completion && tokentab2[i].token == ARROW)
last_was_structop = 1;
return tokentab2[i].token;
}
case '(':
paren_depth++;
lexptr++;
+ if (parse_language->la_language == language_objc && c == '[')
+ return OBJC_LBRAC;
return c;
case ']':
/* Might be a floating point number. */
if (lexptr[1] < '0' || lexptr[1] > '9')
{
- if (in_parse_field)
+ if (parse_completion)
last_was_structop = 1;
goto symbol; /* Nope, must be a symbol. */
}
char *p = &tokstart[1];
size_t len = strlen ("entry");
+ if (parse_language->la_language == language_objc)
+ {
+ size_t len = strlen ("selector");
+
+ if (strncmp (p, "selector", len) == 0
+ && (p[len] == '\0' || isspace (p[len])))
+ {
+ lexptr = p + len;
+ return SELECTOR;
+ }
+ else if (*p == '"')
+ goto parse_string;
+ }
+
while (isspace (*p))
p++;
if (strncmp (p, "entry", len) == 0 && !isalnum (p[len])
/* Fall through. */
case '\'':
case '"':
+
+ parse_string:
{
int host_len;
int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval,
for (i = 0; i < sizeof ident_tokens / sizeof ident_tokens[0]; i++)
if (strcmp (copy, ident_tokens[i].operator) == 0)
{
- if (ident_tokens[i].cxx_only
+ if ((ident_tokens[i].flags & FLAG_CXX) != 0
&& parse_language->la_language != language_cplus)
break;
+ if ((ident_tokens[i].flags & FLAG_SHADOW) != 0)
+ {
+ struct field_of_this_result is_a_field_of_this;
+
+ if (lookup_symbol (copy, expression_context_block,
+ VAR_DOMAIN,
+ (parse_language->la_language == language_cplus
+ ? &is_a_field_of_this
+ : NULL))
+ != NULL)
+ {
+ /* The keyword is shadowed. */
+ break;
+ }
+ }
+
/* It is ok to always set this, even though we don't always
strictly need to. */
yylval.opcode = ident_tokens[i].opcode;
if (*tokstart == '$')
return VARIABLE;
- if (in_parse_field && *lexptr == '\0')
+ if (parse_completion && *lexptr == '\0')
saw_name_at_eof = 1;
return NAME;
}
in which lookups start; this can be NULL to mean the global
scope. */
static int
-classify_name (struct block *block)
+classify_name (const struct block *block)
{
struct symbol *sym;
char *copy;
- int is_a_field_of_this = 0;
+ struct field_of_this_result is_a_field_of_this;
copy = copy_name (yylval.sval);
+ /* Initialize this in case we *don't* use it in this call; that way
+ we can refer to it unconditionally below. */
+ memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this));
+
sym = lookup_symbol (copy, block, VAR_DOMAIN,
- parse_language->la_language == language_cplus
- ? &is_a_field_of_this : (int *) NULL);
+ parse_language->la_name_of_this
+ ? &is_a_field_of_this : NULL);
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
yylval.ssym.sym = sym;
- yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL;
return BLOCKNAME;
}
else if (!sym)
yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
return FILENAME;
}
+
+ /* If we found a field of 'this', we might have erroneously
+ found a constructor where we wanted a type name. Handle this
+ case by noticing that we found a constructor and then look up
+ the type tag instead. */
+ if (is_a_field_of_this.type != NULL
+ && is_a_field_of_this.fn_field != NULL
+ && TYPE_FN_FIELD_CONSTRUCTOR (is_a_field_of_this.fn_field->fn_fields,
+ 0))
+ {
+ struct field_of_this_result inner_is_a_field_of_this;
+
+ sym = lookup_symbol (copy, block, STRUCT_DOMAIN,
+ &inner_is_a_field_of_this);
+ if (sym != NULL)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ }
}
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
if (yylval.tsym.type != NULL)
return TYPENAME;
+ /* See if it's an ObjC classname. */
+ if (parse_language->la_language == language_objc && !sym)
+ {
+ CORE_ADDR Class = lookup_objc_class (parse_gdbarch, copy);
+ if (Class)
+ {
+ yylval.class.class = Class;
+ sym = lookup_struct_typedef (copy, expression_context_block, 1);
+ if (sym)
+ yylval.class.type = SYMBOL_TYPE (sym);
+ return CLASSNAME;
+ }
+ }
+
/* Input names that aren't symbols but ARE valid hex numbers, when
the input radix permits them, can be names or numbers depending
on the parse. Note we support radixes > 16 here. */
if (hextype == INT)
{
yylval.ssym.sym = sym;
- yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL;
return NAME_OR_INT;
}
}
/* Any other kind of symbol */
yylval.ssym.sym = sym;
- yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL;
if (sym == NULL
&& parse_language->la_language == language_cplus
- && !is_a_field_of_this
+ && is_a_field_of_this.type == NULL
&& !lookup_minimal_symbol (copy, NULL, NULL))
return UNKNOWN_CPP_NAME;
in `yylval' is the first component of a name, false otherwise. */
static int
-classify_inner_name (struct block *block, int first_name)
+classify_inner_name (const struct block *block, int first_name)
{
struct type *type, *new_type;
char *copy;