#include "config.h"
#include "system.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
#include "c-lex.h"
#include "lex.h"
#include "cp-parse.h"
#include "flags.h"
#include "obstack.h"
#include "toplev.h"
#include "ggc.h"
#include "intl.h"
#include "timevar.h"
#ifdef PFE
#include "pfe/pfe.h"
#include "pfe/pfe-header.h"
#endif
#ifdef SPEW_DEBUG
#define SPEW_INLINE
#else
#define SPEW_INLINE inline
#endif
struct token
{
short yychar;
unsigned int lineno;
YYSTYPE yylval;
};
struct unparsed_text
{
struct unparsed_text *next;
tree decl;
const char *filename;
int lineno;
int interface;
struct token *pos;
struct token *limit;
};
struct feed
{
struct unparsed_text *input;
const char *filename;
int lineno;
int yychar;
YYSTYPE yylval;
int first_token;
struct obstack token_obstack;
struct feed *next;
};
static struct obstack feed_obstack;
static struct feed *feed;
static SPEW_INLINE void do_aggr PARAMS ((void));
static SPEW_INLINE int identifier_type PARAMS ((tree));
static void scan_tokens PARAMS ((int));
static void feed_defarg PARAMS ((tree));
static void finish_defarg PARAMS ((void));
static int read_token PARAMS ((struct token *));
static SPEW_INLINE int num_tokens PARAMS ((void));
static SPEW_INLINE struct token *nth_token PARAMS ((int));
static SPEW_INLINE int add_token PARAMS ((struct token *));
static SPEW_INLINE int shift_token PARAMS ((void));
static SPEW_INLINE void push_token PARAMS ((struct token *));
static SPEW_INLINE void consume_token PARAMS ((void));
static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *));
static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *));
static SPEW_INLINE void snarf_block PARAMS ((const char *, int));
static tree snarf_defarg PARAMS ((void));
static int frob_id PARAMS ((int, int, tree *));
struct unparsed_text *pending_inlines;
struct unparsed_text *pending_inlines_tail;
struct unparsed_text *processing_these_inlines;
static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *));
static void mark_pending_inlines PARAMS ((PTR));
#ifdef SPEW_DEBUG
int spew_debug = 0;
static unsigned int yylex_ctr = 0;
static void debug_yychar PARAMS ((int));
extern char *debug_yytranslate PARAMS ((int));
#endif
static enum cpp_ttype last_token;
static tree last_token_id;
extern tree lastiddecl;
extern int yychar;
extern YYSTYPE yylval;
struct obstack token_obstack;
int first_token;
struct obstack inline_text_obstack;
char *inline_text_firstobj;
static tree defarg_fns;
static tree defarg_parm;
static tree defarg_depfns;
static tree defarg_fnsdone;
void
init_spew ()
{
gcc_obstack_init (&inline_text_obstack);
inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
gcc_obstack_init (&token_obstack);
gcc_obstack_init (&feed_obstack);
ggc_add_tree_root (&defarg_fns, 1);
ggc_add_tree_root (&defarg_parm, 1);
ggc_add_tree_root (&defarg_depfns, 1);
ggc_add_tree_root (&defarg_fnsdone, 1);
ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *),
mark_pending_inlines);
ggc_add_root (&processing_these_inlines, 1, sizeof (struct unparsed_text *),
mark_pending_inlines);
}
void
clear_inline_text_obstack ()
{
obstack_free (&inline_text_obstack, inline_text_firstobj);
}
static SPEW_INLINE int
read_process_identifier (pyylval)
YYSTYPE *pyylval;
{
tree id = pyylval->ttype;
if (C_IS_RESERVED_WORD (id)
&& (!compiling_objc
|| (!OBJC_IS_AT_KEYWORD (C_RID_CODE (id))
&& (!OBJC_IS_PQ_KEYWORD (C_RID_CODE (id)) || objc_pq_context)))
&& altivec_treat_as_keyword (id))
{
switch (C_RID_CODE (id))
{
case RID_BITAND: pyylval->code = BIT_AND_EXPR; return '&';
case RID_AND_EQ: pyylval->code = BIT_AND_EXPR; return ASSIGN;
case RID_BITOR: pyylval->code = BIT_IOR_EXPR; return '|';
case RID_OR_EQ: pyylval->code = BIT_IOR_EXPR; return ASSIGN;
case RID_XOR: pyylval->code = BIT_XOR_EXPR; return '^';
case RID_XOR_EQ: pyylval->code = BIT_XOR_EXPR; return ASSIGN;
case RID_NOT_EQ: pyylval->code = NE_EXPR; return EQCOMPARE;
case RID_ID:
{
tree decl = NULL_TREE, next_tok;
enum cpp_ttype next_tok_type;
if (!compiling_objc || objc_need_raw_identifier)
return IDENTIFIER;
decl = lookup_name (id, 1);
if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL
|| DECL_CONTEXT (decl) || got_scope)
return IDENTIFIER;
next_tok_type = c_lex (&next_tok);
_cpp_backup_tokens (parse_in, 1);
if (next_tok_type == CPP_SEMICOLON)
return IDENTIFIER;
}
goto get_ridpointer;
case RID_CLASS:
if (compiling_objc && objc_need_raw_identifier
&& !processing_template_decl)
{
return IDENTIFIER;
}
default:
get_ridpointer:
if (C_RID_YYCODE (id) == TYPESPEC)
GNU_xref_ref (current_function_decl, IDENTIFIER_POINTER (id));
pyylval->ttype = ridpointers[C_RID_CODE (id)];
return C_RID_YYCODE (id);
}
}
GNU_xref_ref (current_function_decl, IDENTIFIER_POINTER (id));
#if !defined(JOINER) || JOINER == '$'
if (VPTR_NAME_P (id)
|| VTABLE_NAME_P (id)
|| TEMP_NAME_P (id)
|| ANON_AGGRNAME_P (id))
warning (
"identifier name `%s' conflicts with GNU C++ internal naming strategy",
IDENTIFIER_POINTER (id));
#endif
return IDENTIFIER;
}
static int
read_token (t)
struct token *t;
{
retry:
last_token = c_lex (&last_token_id);
t->yylval.ttype = last_token_id;
switch (last_token)
{
#define YYCHAR(yy) t->yychar = yy; break;
#define YYCODE(c) t->yylval.code = c;
case CPP_EQ: altivec_context = 0; YYCHAR('=');
case CPP_NOT: YYCHAR('!');
case CPP_GREATER: OBJC_NEED_RAW_IDENTIFIER (0); YYCODE(GT_EXPR); YYCHAR('>');
case CPP_LESS: YYCODE(LT_EXPR); YYCHAR('<');
case CPP_PLUS: YYCODE(PLUS_EXPR); YYCHAR('+');
case CPP_MINUS: YYCODE(MINUS_EXPR); YYCHAR('-');
case CPP_MULT: YYCODE(MULT_EXPR); YYCHAR('*');
case CPP_DIV: YYCODE(TRUNC_DIV_EXPR); YYCHAR('/');
case CPP_MOD: YYCODE(TRUNC_MOD_EXPR); YYCHAR('%');
case CPP_AND: YYCODE(BIT_AND_EXPR); YYCHAR('&');
case CPP_OR: YYCODE(BIT_IOR_EXPR); YYCHAR('|');
case CPP_XOR: YYCODE(BIT_XOR_EXPR); YYCHAR('^');
case CPP_RSHIFT: YYCODE(RSHIFT_EXPR); YYCHAR(RSHIFT);
case CPP_LSHIFT: YYCODE(LSHIFT_EXPR); YYCHAR(LSHIFT);
case CPP_COMPL: YYCHAR('~');
case CPP_AND_AND: YYCHAR(ANDAND);
case CPP_OR_OR: YYCHAR(OROR);
case CPP_QUERY: YYCHAR('?');
case CPP_COLON: altivec_context = 0; OBJC_NEED_RAW_IDENTIFIER (0); YYCHAR(':');
case CPP_COMMA: altivec_context = 0; OBJC_NEED_RAW_IDENTIFIER (0); YYCHAR(',');
case CPP_OPEN_PAREN: altivec_context = 0; OBJC_NEED_RAW_IDENTIFIER (0); YYCHAR('(');
case CPP_CLOSE_PAREN: altivec_context = 0; OBJC_NEED_RAW_IDENTIFIER (0); YYCHAR(')');
case CPP_EQ_EQ: YYCODE(EQ_EXPR); YYCHAR(EQCOMPARE);
case CPP_NOT_EQ: YYCODE(NE_EXPR); YYCHAR(EQCOMPARE);
case CPP_GREATER_EQ:YYCODE(GE_EXPR); YYCHAR(ARITHCOMPARE);
case CPP_LESS_EQ: YYCODE(LE_EXPR); YYCHAR(ARITHCOMPARE);
case CPP_PLUS_EQ: YYCODE(PLUS_EXPR); YYCHAR(ASSIGN);
case CPP_MINUS_EQ: YYCODE(MINUS_EXPR); YYCHAR(ASSIGN);
case CPP_MULT_EQ: YYCODE(MULT_EXPR); YYCHAR(ASSIGN);
case CPP_DIV_EQ: YYCODE(TRUNC_DIV_EXPR); YYCHAR(ASSIGN);
case CPP_MOD_EQ: YYCODE(TRUNC_MOD_EXPR); YYCHAR(ASSIGN);
case CPP_AND_EQ: YYCODE(BIT_AND_EXPR); YYCHAR(ASSIGN);
case CPP_OR_EQ: YYCODE(BIT_IOR_EXPR); YYCHAR(ASSIGN);
case CPP_XOR_EQ: YYCODE(BIT_XOR_EXPR); YYCHAR(ASSIGN);
case CPP_RSHIFT_EQ: YYCODE(RSHIFT_EXPR); YYCHAR(ASSIGN);
case CPP_LSHIFT_EQ: YYCODE(LSHIFT_EXPR); YYCHAR(ASSIGN);
case CPP_OPEN_SQUARE: YYCHAR('[');
case CPP_CLOSE_SQUARE: YYCHAR(']');
case CPP_OPEN_BRACE: YYCHAR('{');
case CPP_CLOSE_BRACE: YYCHAR('}');
case CPP_SEMICOLON: altivec_context = 0; OBJC_NEED_RAW_IDENTIFIER (0); YYCHAR(';');
case CPP_ELLIPSIS: YYCHAR(ELLIPSIS);
case CPP_PLUS_PLUS: YYCHAR(PLUSPLUS);
case CPP_MINUS_MINUS: YYCHAR(MINUSMINUS);
case CPP_DEREF: YYCHAR(POINTSAT);
case CPP_DOT: YYCHAR('.');
case CPP_SCOPE: YYCHAR(SCOPE);
case CPP_DEREF_STAR: YYCHAR(POINTSAT_STAR);
case CPP_DOT_STAR: YYCHAR(DOT_STAR);
case CPP_MIN_EQ: YYCODE(MIN_EXPR); YYCHAR(ASSIGN);
case CPP_MAX_EQ: YYCODE(MAX_EXPR); YYCHAR(ASSIGN);
case CPP_MIN: YYCODE(MIN_EXPR); YYCHAR(MIN_MAX);
case CPP_MAX: YYCODE(MAX_EXPR); YYCHAR(MIN_MAX);
#undef YYCHAR
#undef YYCODE
case CPP_EOF:
t->yychar = 0;
break;
case CPP_NAME:
t->yychar = read_process_identifier (&t->yylval);
break;
case CPP_NUMBER:
case CPP_CHAR:
case CPP_WCHAR:
t->yychar = CONSTANT;
break;
case CPP_STRING:
case CPP_WSTRING:
t->yychar = STRING;
break;
case CPP_ATSIGN:
t->yychar = '@';
if (compiling_objc) {
enum cpp_ttype after_at = last_token;
tree after_at_id = last_token_id;
enum rid last_rid;
last_token = c_lex (&last_token_id);
last_rid = C_RID_CODE (last_token_id);
if (last_token == CPP_NAME
&& C_IS_RESERVED_WORD (last_token_id))
{
switch (last_rid) {
case RID_CLASS:
last_rid = RID_AT_CLASS;
goto at_keyword_found;
case RID_PUBLIC:
last_rid = RID_AT_PUBLIC;
goto at_keyword_found;
case RID_PROTECTED:
last_rid = RID_AT_PROTECTED;
goto at_keyword_found;
case RID_PRIVATE:
last_rid = RID_AT_PRIVATE;
goto at_keyword_found;
case RID_AT_INTERFACE:
case RID_AT_IMPLEMENTATION:
case RID_AT_PROTOCOL:
case RID_AT_ALIAS:
case RID_AT_ENCODE:
case RID_AT_DEFS:
case RID_AT_END:
case RID_AT_SELECTOR:
case RID_AT_CLASS:
case RID_AT_PUBLIC:
case RID_AT_PROTECTED:
case RID_AT_PRIVATE:
at_keyword_found:
t->yylval.ttype = last_token_id;
t->yychar = rid_to_yy [(int) last_rid];
break;
default:
goto unget_cpp;
}
}
else
{
unget_cpp:
_cpp_backup_tokens (parse_in, 1);
last_token = after_at;
last_token_id = after_at_id;
}
}
break;
default:
yyerror ("parse error");
goto retry;
}
t->lineno = lineno;
return t->yychar;
}
static void
feed_input (input)
struct unparsed_text *input;
{
struct feed *f;
#if 0
if (feed)
abort ();
#endif
f = obstack_alloc (&feed_obstack, sizeof (struct feed));
input->pos = (struct token *) (input + 1);
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tfeeding %s:%d [%d tokens]\n",
input->filename, input->lineno, input->limit - input->pos);
#endif
f->input = input;
f->filename = input_filename;
f->lineno = lineno;
f->yychar = yychar;
f->yylval = yylval;
f->first_token = first_token;
f->token_obstack = token_obstack;
f->next = feed;
input_filename = input->filename;
lineno = input->lineno;
yychar = YYEMPTY;
yylval.ttype = NULL_TREE;
first_token = 0;
gcc_obstack_init (&token_obstack);
feed = f;
}
void
end_input ()
{
struct feed *f = feed;
input_filename = f->filename;
lineno = f->lineno;
yychar = f->yychar;
yylval = f->yylval;
first_token = f->first_token;
obstack_free (&token_obstack, 0);
token_obstack = f->token_obstack;
feed = f->next;
obstack_free (&feed_obstack, f);
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno);
#endif
}
static void
mark_pending_inlines (pi)
PTR pi;
{
struct unparsed_text *up = * (struct unparsed_text **)pi;
while (up)
{
struct token *t = (struct token *) (up + 1);
struct token *l = up->limit;
while (t < l)
{
switch (t->yychar)
{
case '+': case '-': case '*': case '/':
case '%': case '&': case '|': case '^':
case '>': case '<': case LSHIFT: case RSHIFT:
case ASSIGN: case MIN_MAX: case EQCOMPARE: case ARITHCOMPARE:
t++;
continue;
}
if (t->yylval.ttype)
ggc_mark_tree (t->yylval.ttype);
t++;
}
up = up->next;
}
}
static SPEW_INLINE int
num_tokens ()
{
return (obstack_object_size (&token_obstack) / sizeof (struct token))
- first_token;
}
static SPEW_INLINE struct token*
nth_token (n)
int n;
{
#ifdef ENABLE_CHECKING
my_friendly_assert (n >= 0 && n < num_tokens (), 298);
#endif
return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
}
static const struct token Teosi = { END_OF_SAVED_INPUT, 0 UNION_INIT_ZERO };
static const struct token Tpad = { EMPTY, 0 UNION_INIT_ZERO };
static SPEW_INLINE int
add_token (t)
struct token *t;
{
if (!feed)
return read_token (t);
if (feed->input->pos < feed->input->limit)
{
memcpy (t, feed->input->pos, sizeof (struct token));
return (feed->input->pos++)->yychar;
}
memcpy (t, &Teosi, sizeof (struct token));
return END_OF_SAVED_INPUT;
}
static SPEW_INLINE int
shift_token ()
{
size_t point = obstack_object_size (&token_obstack);
obstack_blank (&token_obstack, sizeof (struct token));
return add_token ((struct token *) (obstack_base (&token_obstack) + point));
}
static SPEW_INLINE void
consume_token ()
{
if (num_tokens () == 1)
{
obstack_free (&token_obstack, obstack_base (&token_obstack));
first_token = 0;
}
else
first_token++;
}
static SPEW_INLINE void
push_token (t)
struct token *t;
{
if (first_token == 0)
{
size_t active = obstack_object_size (&token_obstack);
obstack_blank (&token_obstack, sizeof (struct token));
if (active)
memmove (obstack_base (&token_obstack) + sizeof (struct token),
obstack_base (&token_obstack), active);
first_token++;
}
first_token--;
memcpy (nth_token (0), t, sizeof (struct token));
}
static void
scan_tokens (n)
int n;
{
int i;
int num = num_tokens ();
int yychar;
i = num;
while (i > 0 && nth_token (i - 1)->yychar == EMPTY)
i--;
if (i < num)
{
obstack_blank (&token_obstack, -((num - i) * sizeof (struct token)));
num = i;
}
if (num > n)
return;
for (i = 0; i < num; i++)
{
yychar = nth_token (i)->yychar;
if (yychar == '{' || yychar == ':' || yychar == ';')
goto pad_tokens;
}
while (num_tokens () <= n)
{
yychar = shift_token ();
if (yychar == '{' || yychar == ':' || yychar == ';')
goto pad_tokens;
}
return;
pad_tokens:
while (num_tokens () <= n)
obstack_grow (&token_obstack, &Tpad, sizeof (struct token));
}
int looking_for_typename;
int looking_for_template;
static int after_friend;
static int after_new;
static int do_snarf_defarg;
tree got_scope;
tree got_object;
static SPEW_INLINE int
identifier_type (decl)
tree decl;
{
tree t;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == TYPE_DECL)
return PTYPENAME;
else if (looking_for_template)
return PFUNCNAME;
}
if (looking_for_template && really_overloaded_fn (decl))
{
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
return NSNAME;
if (TREE_CODE (decl) != TYPE_DECL)
return IDENTIFIER;
if (DECL_ARTIFICIAL (decl) && TREE_TYPE (decl) == current_class_type)
return SELFNAME;
t = got_scope;
if (t && TREE_CODE (t) == TYPENAME_TYPE)
t = TREE_TYPE (t);
decl = TREE_TYPE (decl);
if (TREE_CODE (decl) == TYPENAME_TYPE)
decl = TREE_TYPE (decl);
if (t && t == decl)
return SELFNAME;
return TYPENAME;
}
static SPEW_INLINE void
do_aggr ()
{
int yc1, yc2;
scan_tokens (2);
yc1 = nth_token (1)->yychar;
if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
return;
yc2 = nth_token (2)->yychar;
if (yc2 == ';')
{
if (after_friend || after_new)
return;
}
else if (yc2 != '{' && yc2 != ':')
return;
switch (yc1)
{
case TYPENAME:
nth_token (1)->yychar = TYPENAME_DEFN;
break;
case PTYPENAME:
nth_token (1)->yychar = PTYPENAME_DEFN;
break;
case IDENTIFIER:
nth_token (1)->yychar = IDENTIFIER_DEFN;
break;
default:
my_friendly_abort (102);
}
}
void
see_typename ()
{
looking_for_typename = 2;
if (yychar < 0)
if ((yychar = yylex ()) < 0) yychar = 0;
looking_for_typename = 0;
if (yychar == IDENTIFIER)
{
lastiddecl = lookup_name (yylval.ttype, -2);
if (lastiddecl)
yychar = identifier_type (lastiddecl);
}
}
int
yylex ()
{
int yychr;
int old_looking_for_typename = 0;
int just_saw_new = 0;
int just_saw_friend = 0;
timevar_push (TV_LEX);
retry:
#ifdef SPEW_DEBUG
if (spew_debug)
{
yylex_ctr ++;
fprintf (stderr, "\t\t## %d @%d ", yylex_ctr, lineno);
}
#endif
if (do_snarf_defarg)
{
do_snarf_defarg = 0;
yylval.ttype = snarf_defarg ();
yychar = DEFARG;
got_object = NULL_TREE;
timevar_pop (TV_LEX);
return DEFARG;
}
else if (num_tokens ())
yychr = nth_token (0)->yychar;
else
yychr = shift_token ();
switch (yychr)
{
case EMPTY:
#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
consume_token ();
goto retry;
case '(':
scan_tokens (1);
if (nth_token (1)->yychar == ')')
{
consume_token ();
yychr = LEFT_RIGHT;
}
break;
case IDENTIFIER:
{
int peek;
scan_tokens (1);
peek = nth_token (1)->yychar;
yychr = frob_id (yychr, peek, &nth_token (0)->yylval.ttype);
if (compiling_objc && peek == AGGR
&& nth_token (1)->yylval.ttype == ridpointers[RID_CLASS])
{
nth_token (1)->yychar = IDENTIFIER;
nth_token (1)->yylval.ttype = get_identifier ("class");
}
break;
}
case IDENTIFIER_DEFN:
case TYPENAME:
case TYPENAME_DEFN:
case PTYPENAME:
case PTYPENAME_DEFN:
looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
break;
case SCSPEC:
if (nth_token (0)->yylval.ttype == ridpointers[RID_EXTERN])
{
scan_tokens (1);
if (nth_token (1)->yychar == STRING)
{
yychr = EXTERN_LANG_STRING;
nth_token (1)->yylval.ttype = get_identifier
(TREE_STRING_POINTER (nth_token (1)->yylval.ttype));
consume_token ();
}
}
else if (nth_token (0)->yylval.ttype == ridpointers[RID_FRIEND])
just_saw_friend = 1;
break;
case NEW:
just_saw_new = 1;
break;
case ';':
OBJC_NEED_RAW_IDENTIFIER (0);
looking_for_typename = 0;
break;
case TYPESPEC:
OBJC_NEED_RAW_IDENTIFIER (1);
case ':':
case '{':
looking_for_typename = 0;
break;
case AGGR:
do_aggr ();
break;
case ENUM:
looking_for_typename = 2;
break;
default:
break;
}
after_friend = just_saw_friend;
after_new = just_saw_new;
if (yychr != '~')
got_object = NULL_TREE;
yychar = yychr;
{
struct token *tok = nth_token (0);
yylval = tok->yylval;
if (tok->lineno)
lineno = tok->lineno;
}
#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
consume_token ();
timevar_pop (TV_LEX);
return yychr;
}
void
yyungetc (ch, rescan)
int ch;
int rescan;
{
if (yychar == YYEMPTY || rescan == 0)
{
struct token fake;
if (ch == '{')
indent_level--;
else if (ch == '}')
indent_level++;
fake.yychar = ch;
fake.yylval.ttype = 0;
fake.lineno = lineno;
push_token (&fake);
}
else
{
yychar = ch;
}
}
static int
frob_id (yyc, peek, idp)
int yyc;
int peek;
tree *idp;
{
tree trrr;
int old_looking_for_typename = 0;
if (peek == SCOPE)
{
old_looking_for_typename = looking_for_typename;
looking_for_typename = 1;
}
else if (peek == '<')
looking_for_template = 1;
trrr = lookup_name (*idp, -2);
if (trrr)
{
yyc = identifier_type (trrr);
switch(yyc)
{
case TYPENAME:
if (compiling_objc && peek == '<')
{
tree objc_interface_decl = is_class_name (*idp);
if (objc_interface_decl)
{
trrr = objc_interface_decl;
yyc = CLASSNAME;
}
}
case SELFNAME:
case NSNAME:
case PTYPENAME:
if (got_scope || got_object)
*idp = trrr;
case PFUNCNAME:
case IDENTIFIER:
lastiddecl = trrr;
break;
default:
my_friendly_abort (20000907);
}
}
else if (compiling_objc)
{
tree objc_interface_decl = is_class_name (*idp);
if (objc_interface_decl && !objc_need_raw_identifier)
{
*idp = objc_interface_decl;
yyc = CLASSNAME;
}
lastiddecl = objc_interface_decl;
}
else
lastiddecl = NULL_TREE;
got_scope = NULL_TREE;
looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
return yyc;
}
tree frob_opname (id)
tree id;
{
scan_tokens (0);
frob_id (0, nth_token (0)->yychar, &id);
got_object = NULL_TREE;
return id;
}
static void
begin_parsing_inclass_inline (pi)
struct unparsed_text *pi;
{
tree context;
processing_these_inlines = pi;
ggc_collect ();
context = decl_function_context (pi->decl);
if (context)
push_function_context_to (context);
feed_input (pi);
interface_unknown = pi->interface == 1;
interface_only = pi->interface == 0;
DECL_PENDING_INLINE_P (pi->decl) = 0;
DECL_PENDING_INLINE_INFO (pi->decl) = 0;
yychar = PRE_PARSED_FUNCTION_DECL;
yylval.pi = pi;
start_function (NULL_TREE, pi->decl, NULL_TREE,
(SF_DEFAULT | SF_PRE_PARSED | SF_INCLASS_INLINE));
}
void
do_pending_inlines ()
{
if (yychar == PRE_PARSED_FUNCTION_DECL)
return;
if (pending_inlines)
{
struct unparsed_text *first = pending_inlines;
pending_inlines = pending_inlines_tail = 0;
begin_parsing_inclass_inline (first);
}
}
void
process_next_inline (i)
struct unparsed_text *i;
{
tree decl = i->decl;
tree context = decl_function_context (decl);
if (context)
pop_function_context_from (context);
if (yychar == YYEMPTY)
yychar = yylex ();
if (yychar != END_OF_SAVED_INPUT)
error ("parse error at end of saved function text");
end_input ();
i = i->next;
if (i)
begin_parsing_inclass_inline (i);
else
{
processing_these_inlines = 0;
extract_interface_info ();
}
}
static SPEW_INLINE void
snarf_block (starting_file, starting_line)
const char *starting_file;
int starting_line;
{
int blev = 1;
int look_for_semicolon = 0;
int look_for_lbrac = 0;
int look_for_catch = 0;
int yyc;
struct token tmp;
size_t point;
if (yychar == '{')
indent_level--;
else if (yychar == '=')
look_for_semicolon = 1;
else if (yychar == ':' || yychar == RETURN_KEYWORD || yychar == TRY)
{
if (yychar == TRY)
look_for_catch = 1;
look_for_lbrac = 1;
blev = 0;
}
else
yyerror ("parse error in method specification");
tmp.yychar = yychar;
tmp.yylval = yylval;
tmp.lineno = lineno;
obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
for (;;)
{
point = obstack_object_size (&inline_text_obstack);
obstack_blank (&inline_text_obstack, sizeof (struct token));
yyc = add_token ((struct token *)
(obstack_base (&inline_text_obstack) + point));
if (yyc == '{')
{
look_for_lbrac = 0;
blev++;
}
else if (yyc == '}')
{
blev--;
if (blev == 0 && !look_for_semicolon)
{
if (!look_for_catch)
break;
if (add_token (&tmp) != CATCH)
{
push_token (&tmp);
break;
}
look_for_lbrac = 1;
obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
}
}
else if (yyc == ';')
{
if (look_for_lbrac)
{
error ("function body for constructor missing");
tmp.yylval.ttype = 0;
tmp.yychar = '{';
obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
tmp.yychar = '}';
obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
break;
}
else if (look_for_semicolon && blev == 0)
break;
}
else if (yyc == 0)
{
error_with_file_and_line (starting_file, starting_line,
"end of file read inside definition");
break;
}
}
}
void
snarf_method (decl)
tree decl;
{
int starting_lineno = lineno;
const char *starting_filename = input_filename;
size_t len;
struct unparsed_text *meth;
obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
snarf_block (starting_filename, starting_lineno);
len = obstack_object_size (&inline_text_obstack);
meth = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
if (decl == void_type_node
|| (current_class_type && TYPE_REDEFINED (current_class_type)))
{
obstack_free (&inline_text_obstack, (char *)meth);
return;
}
meth->decl = decl;
meth->filename = starting_filename;
meth->lineno = starting_lineno;
meth->limit = (struct token *) ((char *)meth + len);
meth->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
meth->next = 0;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n",
meth->limit - (struct token *) (meth + 1),
starting_filename, starting_lineno);
#endif
DECL_PENDING_INLINE_INFO (decl) = meth;
DECL_PENDING_INLINE_P (decl) = 1;
if (pending_inlines_tail)
pending_inlines_tail->next = meth;
else
pending_inlines = meth;
pending_inlines_tail = meth;
}
static tree
snarf_defarg ()
{
int starting_lineno = lineno;
const char *starting_filename = input_filename;
int yyc;
int plev = 0;
size_t point;
size_t len;
struct unparsed_text *buf;
tree arg;
obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
for (;;)
{
point = obstack_object_size (&inline_text_obstack);
obstack_blank (&inline_text_obstack, sizeof (struct token));
yyc = add_token ((struct token *)
(obstack_base (&inline_text_obstack) + point));
if (plev <= 0 && (yyc == ')' || yyc == ','))
break;
else if (yyc == '(' || yyc == '[')
++plev;
else if (yyc == ']' || yyc == ')')
--plev;
else if (yyc == 0)
{
error_with_file_and_line (starting_filename, starting_lineno,
"end of file read inside default argument");
goto done;
}
}
push_token ((struct token *) (obstack_base (&inline_text_obstack) + point));
obstack_blank (&inline_text_obstack, - (int) sizeof (struct token));
done:
len = obstack_object_size (&inline_text_obstack);
buf = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
buf->decl = 0;
buf->filename = starting_filename;
buf->lineno = starting_lineno;
buf->limit = (struct token *) ((char *)buf + len);
buf->next = 0;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n",
buf->limit - (struct token *) (buf + 1),
starting_filename, starting_lineno);
#endif
arg = make_node (DEFAULT_ARG);
DEFARG_POINTER (arg) = (char *)buf;
return arg;
}
void
maybe_snarf_defarg ()
{
if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
do_snarf_defarg = 1;
}
void
add_defarg_fn (decl)
tree decl;
{
if (TREE_CODE (decl) == FUNCTION_DECL)
TREE_VALUE (defarg_fns) = decl;
else
{
defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);
TREE_TYPE (defarg_fns) = current_class_type;
}
}
static void
feed_defarg (p)
tree p;
{
tree d = TREE_PURPOSE (p);
feed_input ((struct unparsed_text *)DEFARG_POINTER (d));
yychar = DEFARG_MARKER;
yylval.ttype = p;
}
static void
finish_defarg ()
{
if (yychar == YYEMPTY)
yychar = yylex ();
if (yychar != END_OF_SAVED_INPUT)
error ("parse error at end of saved function text");
end_input ();
}
void
do_pending_defargs ()
{
if (defarg_parm)
finish_defarg ();
for (; defarg_fns;)
{
tree current = defarg_fns;
tree defarg_fn = TREE_VALUE (defarg_fns);
if (defarg_parm == NULL_TREE)
{
push_nested_class (TREE_TYPE (defarg_fns), 1);
pushlevel (0);
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
maybe_begin_member_template_processing (defarg_fn);
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn));
else
defarg_parm = TYPE_ARG_TYPES (defarg_fn);
}
else
defarg_parm = TREE_CHAIN (defarg_parm);
for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm))
if (!TREE_PURPOSE (defarg_parm)
|| TREE_CODE (TREE_PURPOSE (defarg_parm)) != DEFAULT_ARG)
;
else if (TREE_PURPOSE (current) == error_mark_node)
DEFARG_POINTER (TREE_PURPOSE (defarg_parm)) = NULL;
else
{
feed_defarg (defarg_parm);
return;
}
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
maybe_end_member_template_processing ();
check_default_args (defarg_fn);
}
poplevel (0, 0, 0);
pop_nested_class ();
defarg_fns = TREE_CHAIN (defarg_fns);
if (defarg_depfns)
{
tree a, b;
for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b;
a = TREE_CHAIN (a), b = TREE_CHAIN (b))
if (TREE_VALUE (a) != TREE_VALUE (b))
goto different;
if (a || b)
{
different:;
TREE_CHAIN (current) = NULL_TREE;
defarg_fns = chainon (defarg_fns, current);
TREE_PURPOSE (current) = defarg_depfns;
}
else
{
cp_warning_at ("circular dependency in default args of `%#D'", defarg_fn);
defarg_fns = current;
TREE_PURPOSE (current) = error_mark_node;
}
defarg_depfns = NULL_TREE;
}
else if (TREE_PURPOSE (current) == error_mark_node)
defarg_fnsdone = tree_cons (NULL_TREE, defarg_fn, defarg_fnsdone);
}
}
void
done_pending_defargs ()
{
for (; defarg_fnsdone; defarg_fnsdone = TREE_CHAIN (defarg_fnsdone))
{
tree fn = TREE_VALUE (defarg_fnsdone);
tree parms;
if (TREE_CODE (fn) == FUNCTION_DECL)
parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
else
parms = TYPE_ARG_TYPES (fn);
for (; parms; parms = TREE_CHAIN (parms))
if (TREE_PURPOSE (parms)
&& TREE_CODE (TREE_PURPOSE (parms)) == DEFAULT_ARG)
{
my_friendly_assert (!DEFARG_POINTER (TREE_PURPOSE (parms)), 20010107);
TREE_PURPOSE (parms) = NULL_TREE;
}
}
}
void
unprocessed_defarg_fn (fn)
tree fn;
{
defarg_depfns = tree_cons (NULL_TREE, fn, defarg_depfns);
}
void
replace_defarg (arg, init)
tree arg, init;
{
if (init == error_mark_node)
TREE_PURPOSE (arg) = error_mark_node;
else
{
if (! processing_template_decl
&& ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg));
if (!defarg_depfns)
TREE_PURPOSE (arg) = init;
}
}
#ifdef SPEW_DEBUG
static void
debug_yychar (yy)
int yy;
{
if (yy<256)
fprintf (stderr, "->%d < %c >\n", lineno, yy);
else if (yy == IDENTIFIER || yy == TYPENAME)
{
const char *id;
if (TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
id = IDENTIFIER_POINTER (yylval.ttype);
else if (TREE_CODE_CLASS (TREE_CODE (yylval.ttype)) == 'd')
id = IDENTIFIER_POINTER (DECL_NAME (yylval.ttype));
else
id = "";
fprintf (stderr, "->%d <%s `%s'>\n", lineno, debug_yytranslate (yy), id);
}
else
fprintf (stderr, "->%d <%s>\n", lineno, debug_yytranslate (yy));
}
#endif
#define NAME(type) cpp_type2name (type)
void
yyerror (msgid)
const char *msgid;
{
const char *string = _(msgid);
if (last_token == CPP_EOF)
error ("%s at end of input", string);
else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
{
unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
if (val <= UCHAR_MAX && ISGRAPH (val))
error ("%s before %s'%c'", string, ell, val);
else
error ("%s before %s'\\x%x'", string, ell, val);
}
else if (last_token == CPP_STRING
|| last_token == CPP_WSTRING)
error ("%s before string constant", string);
else if (last_token == CPP_NUMBER)
error ("%s before numeric constant", string);
else if (last_token == CPP_NAME)
{
if (last_token_id && TREE_CODE (last_token_id) == IDENTIFIER_NODE)
error ("%s before `%s'", string, IDENTIFIER_POINTER (last_token_id));
else if (ISGRAPH (yychar))
error ("%s before `%c'", string, yychar);
else
error ("%s before `\%o'", string, yychar);
}
else
error ("%s before `%s' token", string, NAME (last_token));
}
#ifdef PFE
void
pfe_freeze_thaw_unparsed_text (pp)
struct unparsed_text **pp;
{
struct unparsed_text *p = (struct unparsed_text *)PFE_FREEZE_THAW_PTR (pp);
while (p)
{
PFE_FREEZE_THAW_WALK (p->decl);
pfe_freeze_thaw_ptr_fp (&p->filename);
pfe_freeze_thaw_ptr_fp (&p->pos);
pfe_freeze_thaw_ptr_fp (&p->limit);
p = (struct unparsed_text *)PFE_FREEZE_THAW_PTR (&p->next);
}
}
DEFINE_CHECK_STRUCT_FUNCTION (unparsed_text)
#endif