/* Seperate lexical analyzer for GNU C++.
Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file is the lexical analyzer for GNU C++. */
#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
extern int errno
; /* needed for VAX. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern struct obstack
*expression_obstack
, permanent_obstack
;
extern struct obstack
*current_obstack
, *saveable_obstack
;
extern char *get_directive_line (); /* In c-common.c */
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
#ifndef FILE_NAME_NONDIRECTORY
#define FILE_NAME_NONDIRECTORY(X) \
(rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X)
void extract_interface_info ();
/* This obstack is needed to hold text. It is not safe to use
TOKEN_BUFFER because `check_newline' calls `yylex'. */
static struct obstack inline_text_obstack
;
static char *inline_text_firstobj
;
extern struct obstack token_obstack
;
/* ??? Don't really know where this goes yet. */
extern void put_back (/* int */);
extern int input_redirected ();
extern void feed_input (/* char *, int, struct obstack * */);
/* Holds translations from TREE_CODEs to operator name strings,
i.e., opname_tab[PLUS_EXPR] == "+". */
extern int yychar
; /* the lookahead symbol */
extern YYSTYPE yylval
; /* the semantic value of the */
YYLTYPE yylloc
; /* location data for the lookahead */
/* the declaration found for the last IDENTIFIER token read in.
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
used in a context which makes it a reference to a variable. */
/* The elements of `ridpointers' are identifier nodes
for the reserved type names and storage classes.
It is indexed by a RID_... value. */
tree ridpointers
[(int) RID_MAX
];
/* We may keep statistics about how long which files took to compile. */
static int header_time
, body_time
;
static tree
get_time_identifier ();
static tree filename_times
;
static tree this_filename_time
;
/* For implementing #pragma unit. */
tree current_unit_language
;
/* Array for holding counts of the numbers of tokens seen. */
/* Textual definition used for default functions. */
static char default_def
[] = "{}";
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
TYPE_QUALS is a list of modifiers such as const or volatile
to apply to the pointer type, represented as identifiers.
We return an INDIRECT_REF whose "contents" are TARGET
and whose type is the modifier list. */
make_pointer_declarator (type_quals
, target
)
if (target
&& TREE_CODE (target
) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target
))
error ("type name expected before `*'");
target
= build_parse_node (INDIRECT_REF
, target
);
TREE_TYPE (target
) = type_quals
;
/* Return something to represent absolute declarators containing a &.
TARGET is the absolute declarator that the & contains.
TYPE_QUALS is a list of modifiers such as const or volatile
to apply to the reference type, represented as identifiers.
We return an ADDR_EXPR whose "contents" are TARGET
and whose type is the modifier list. */
make_reference_declarator (type_quals
, target
)
if (TREE_CODE (target
) == ADDR_EXPR
)
error ("cannot declare references to references");
if (TREE_CODE (target
) == INDIRECT_REF
)
error ("cannot declare pointers to references");
if (TREE_CODE (target
) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target
))
error ("type name expected before `&'");
target
= build_parse_node (ADDR_EXPR
, target
);
TREE_TYPE (target
) = type_quals
;
/* Build names and nodes for overloaded operators. */
tree ansi_opname
[LAST_CPLUS_TREE_CODE
];
tree ansi_assopname
[LAST_CPLUS_TREE_CODE
];
operator_name_string (name
)
char *opname
= IDENTIFIER_POINTER (name
) + 2;
/* Works for builtin and user defined types. */
if (IDENTIFIER_GLOBAL_VALUE (name
)
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name
)) == TYPE_DECL
)
return IDENTIFIER_POINTER (name
);
if (opname
[0] == 'a' && opname
[2] != '\0')
opname_table
= ansi_assopname
;
opname_table
= ansi_opname
;
for (i
= 0; i
< (int) LAST_CPLUS_TREE_CODE
; i
++)
if (opname
[0] == IDENTIFIER_POINTER (opname_table
[i
])[2+assign
]
&& opname
[1] == IDENTIFIER_POINTER (opname_table
[i
])[3+assign
])
if (i
== LAST_CPLUS_TREE_CODE
)
return "<invalid operator>";
int interface_only
; /* whether or not current file is only for
interface definitions. */
int interface_unknown
; /* whether or not we know this class
to behave according to #pragma interface. */
/* File used for outputting assembler code. */
extern FILE *asm_out_file
;
#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
/* Number of bytes in a wide character. */
#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
static int maxtoken
; /* Current nominal length of token buffer. */
char *token_buffer
; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */
/* Nonzero tells yylex to ignore \ in string constants. */
static int ignore_escape_flag
= 0;
static int skip_white_space ();
get_time_identifier (name
)
char *buf
= (char *)alloca (len
+ 6);
bcopy (name
, buf
+5, len
);
time_identifier
= get_identifier (buf
);
if (IDENTIFIER_LOCAL_VALUE (time_identifier
) == NULL_TREE
)
push_obstacks_nochange ();
end_temporary_allocation ();
IDENTIFIER_LOCAL_VALUE (time_identifier
) = build_int_2 (0, 0);
IDENTIFIER_CLASS_VALUE (time_identifier
) = build_int_2 (0, 1);
IDENTIFIER_GLOBAL_VALUE (time_identifier
) = filename_times
;
filename_times
= time_identifier
;
int old_quiet_flag
= quiet_flag
;
this_time
= get_run_time ();
quiet_flag
= old_quiet_flag
;
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
t, d, s, c, r, <, 1 and 2. See cp-tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
char *cplus_tree_code_type
[] = {
/* Table indexed by tree code giving number of expression
operands beyond the fixed part of the node structure.
Not used for types or decls. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
int cplus_tree_code_length
[] = {
/* Names of tree components.
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
char *cplus_tree_code_name
[] = {
/* toplev.c needs to call these. */
/* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
put_back (check_newline ());
if (flag_gnu_xref
) GNU_xref_begin (input_filename
);
extern int errorcount
, sorrycount
;
if (flag_gnu_xref
) GNU_xref_end (errorcount
+sorrycount
);
this_filename_time
= get_time_identifier ("<top level>");
if (flag_detailed_statistics
)
body_time
= my_get_run_time ();
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
)) = body_time
;
/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
Stuck this hack in to get the files open correctly; this is called
in place of init_lex if we are an unexec'd binary. */
reinit_search_statistics ();
extern int *init_parse ();
extern char *(*decl_printable_name
) ();
extern char *lang_printable_name ();
/* Initialize the lookahead machinery. */
/* Make identifier nodes long enough for the language-specific slots. */
set_identifier_size (sizeof (struct lang_identifier
));
decl_printable_name
= lang_printable_name
;
= (char **) realloc (tree_code_type
,
sizeof (char *) * LAST_CPLUS_TREE_CODE
);
= (int *) realloc (tree_code_length
,
sizeof (int) * LAST_CPLUS_TREE_CODE
);
= (char **) realloc (tree_code_name
,
sizeof (char *) * LAST_CPLUS_TREE_CODE
);
bcopy ((char *)cplus_tree_code_type
,
(char *)(tree_code_type
+ (int) LAST_AND_UNUSED_TREE_CODE
),
(LAST_CPLUS_TREE_CODE
- (int)LAST_AND_UNUSED_TREE_CODE
) * sizeof (char *));
bcopy ((char *)cplus_tree_code_length
,
(char *)(tree_code_length
+ (int) LAST_AND_UNUSED_TREE_CODE
),
(LAST_CPLUS_TREE_CODE
- (int)LAST_AND_UNUSED_TREE_CODE
) * sizeof (int));
bcopy ((char *)cplus_tree_code_name
,
(char *)(tree_code_name
+ (int) LAST_AND_UNUSED_TREE_CODE
),
(LAST_CPLUS_TREE_CODE
- (int)LAST_AND_UNUSED_TREE_CODE
) * sizeof (char *));
opname_tab
= (char **)oballoc ((int)LAST_CPLUS_TREE_CODE
* sizeof (char *));
bzero ((char *)opname_tab
, (int)LAST_CPLUS_TREE_CODE
* sizeof (char *));
assignop_tab
= (char **)oballoc ((int)LAST_CPLUS_TREE_CODE
* sizeof (char *));
bzero ((char *)assignop_tab
, (int)LAST_CPLUS_TREE_CODE
* sizeof (char *));
ansi_opname
[0] = get_identifier ("<invalid operator>");
for (i
= 0; i
< (int) LAST_CPLUS_TREE_CODE
; i
++)
ansi_opname
[i
] = ansi_opname
[0];
ansi_assopname
[i
] = ansi_opname
[0];
ansi_opname
[(int) MULT_EXPR
] = get_identifier ("__ml");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MULT_EXPR
]) = 1;
ansi_opname
[(int) INDIRECT_REF
] = ansi_opname
[(int) MULT_EXPR
];
ansi_assopname
[(int) MULT_EXPR
] = get_identifier ("__aml");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) MULT_EXPR
]) = 1;
ansi_assopname
[(int) INDIRECT_REF
] = ansi_assopname
[(int) MULT_EXPR
];
ansi_opname
[(int) TRUNC_MOD_EXPR
] = get_identifier ("__md");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) TRUNC_MOD_EXPR
]) = 1;
ansi_assopname
[(int) TRUNC_MOD_EXPR
] = get_identifier ("__amd");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) TRUNC_MOD_EXPR
]) = 1;
ansi_opname
[(int) CEIL_MOD_EXPR
] = ansi_opname
[(int) TRUNC_MOD_EXPR
];
ansi_opname
[(int) FLOOR_MOD_EXPR
] = ansi_opname
[(int) TRUNC_MOD_EXPR
];
ansi_opname
[(int) ROUND_MOD_EXPR
] = ansi_opname
[(int) TRUNC_MOD_EXPR
];
ansi_opname
[(int) MINUS_EXPR
] = get_identifier ("__mi");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MINUS_EXPR
]) = 1;
ansi_opname
[(int) NEGATE_EXPR
] = ansi_opname
[(int) MINUS_EXPR
];
ansi_assopname
[(int) MINUS_EXPR
] = get_identifier ("__ami");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) MINUS_EXPR
]) = 1;
ansi_assopname
[(int) NEGATE_EXPR
] = ansi_assopname
[(int) MINUS_EXPR
];
ansi_opname
[(int) RSHIFT_EXPR
] = get_identifier ("__rs");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) RSHIFT_EXPR
]) = 1;
ansi_assopname
[(int) RSHIFT_EXPR
] = get_identifier ("__ars");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) RSHIFT_EXPR
]) = 1;
ansi_opname
[(int) NE_EXPR
] = get_identifier ("__ne");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) NE_EXPR
]) = 1;
ansi_opname
[(int) GT_EXPR
] = get_identifier ("__gt");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) GT_EXPR
]) = 1;
ansi_opname
[(int) GE_EXPR
] = get_identifier ("__ge");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) GE_EXPR
]) = 1;
ansi_opname
[(int) BIT_IOR_EXPR
] = get_identifier ("__or");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) BIT_IOR_EXPR
]) = 1;
ansi_assopname
[(int) BIT_IOR_EXPR
] = get_identifier ("__aor");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) BIT_IOR_EXPR
]) = 1;
ansi_opname
[(int) TRUTH_ANDIF_EXPR
] = get_identifier ("__aa");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) TRUTH_ANDIF_EXPR
]) = 1;
ansi_opname
[(int) TRUTH_NOT_EXPR
] = get_identifier ("__nt");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) TRUTH_NOT_EXPR
]) = 1;
ansi_opname
[(int) PREINCREMENT_EXPR
] = get_identifier ("__pp");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) PREINCREMENT_EXPR
]) = 1;
ansi_opname
[(int) POSTINCREMENT_EXPR
] = ansi_opname
[(int) PREINCREMENT_EXPR
];
ansi_opname
[(int) MODIFY_EXPR
] = get_identifier ("__as");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MODIFY_EXPR
]) = 1;
ansi_assopname
[(int) NOP_EXPR
] = ansi_opname
[(int) MODIFY_EXPR
];
ansi_opname
[(int) COMPOUND_EXPR
] = get_identifier ("__cm");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) COMPOUND_EXPR
]) = 1;
ansi_opname
[(int) EXACT_DIV_EXPR
] = get_identifier ("__dv");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) EXACT_DIV_EXPR
]) = 1;
ansi_assopname
[(int) EXACT_DIV_EXPR
] = get_identifier ("__adv");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) EXACT_DIV_EXPR
]) = 1;
ansi_opname
[(int) TRUNC_DIV_EXPR
] = ansi_opname
[(int) EXACT_DIV_EXPR
];
ansi_opname
[(int) CEIL_DIV_EXPR
] = ansi_opname
[(int) EXACT_DIV_EXPR
];
ansi_opname
[(int) FLOOR_DIV_EXPR
] = ansi_opname
[(int) EXACT_DIV_EXPR
];
ansi_opname
[(int) ROUND_DIV_EXPR
] = ansi_opname
[(int) EXACT_DIV_EXPR
];
ansi_opname
[(int) PLUS_EXPR
] = get_identifier ("__pl");
ansi_assopname
[(int) TRUNC_DIV_EXPR
] = ansi_assopname
[(int) EXACT_DIV_EXPR
];
ansi_assopname
[(int) CEIL_DIV_EXPR
] = ansi_assopname
[(int) EXACT_DIV_EXPR
];
ansi_assopname
[(int) FLOOR_DIV_EXPR
] = ansi_assopname
[(int) EXACT_DIV_EXPR
];
ansi_assopname
[(int) ROUND_DIV_EXPR
] = ansi_assopname
[(int) EXACT_DIV_EXPR
];
ansi_opname
[(int) PLUS_EXPR
] = get_identifier ("__pl");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) PLUS_EXPR
]) = 1;
ansi_assopname
[(int) PLUS_EXPR
] = get_identifier ("__apl");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) PLUS_EXPR
]) = 1;
ansi_opname
[(int) CONVERT_EXPR
] = ansi_opname
[(int) PLUS_EXPR
];
ansi_assopname
[(int) CONVERT_EXPR
] = ansi_assopname
[(int) PLUS_EXPR
];
ansi_opname
[(int) LSHIFT_EXPR
] = get_identifier ("__ls");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) LSHIFT_EXPR
]) = 1;
ansi_assopname
[(int) LSHIFT_EXPR
] = get_identifier ("__als");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) LSHIFT_EXPR
]) = 1;
ansi_opname
[(int) EQ_EXPR
] = get_identifier ("__eq");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) EQ_EXPR
]) = 1;
ansi_opname
[(int) LT_EXPR
] = get_identifier ("__lt");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) LT_EXPR
]) = 1;
ansi_opname
[(int) LE_EXPR
] = get_identifier ("__le");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) LE_EXPR
]) = 1;
ansi_opname
[(int) BIT_AND_EXPR
] = get_identifier ("__ad");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) BIT_AND_EXPR
]) = 1;
ansi_assopname
[(int) BIT_AND_EXPR
] = get_identifier ("__aad");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) BIT_AND_EXPR
]) = 1;
ansi_opname
[(int) ADDR_EXPR
] = ansi_opname
[(int) BIT_AND_EXPR
];
ansi_assopname
[(int) ADDR_EXPR
] = ansi_assopname
[(int) BIT_AND_EXPR
];
ansi_opname
[(int) BIT_XOR_EXPR
] = get_identifier ("__er");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) BIT_XOR_EXPR
]) = 1;
ansi_assopname
[(int) BIT_XOR_EXPR
] = get_identifier ("__aer");
IDENTIFIER_OPNAME_P (ansi_assopname
[(int) BIT_XOR_EXPR
]) = 1;
ansi_opname
[(int) TRUTH_ORIF_EXPR
] = get_identifier ("__oo");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) TRUTH_ORIF_EXPR
]) = 1;
ansi_opname
[(int) BIT_NOT_EXPR
] = get_identifier ("__co");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) BIT_NOT_EXPR
]) = 1;
ansi_opname
[(int) PREDECREMENT_EXPR
] = get_identifier ("__mm");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) PREDECREMENT_EXPR
]) = 1;
ansi_opname
[(int) POSTDECREMENT_EXPR
] = ansi_opname
[(int) PREDECREMENT_EXPR
];
ansi_opname
[(int) COMPONENT_REF
] = get_identifier ("__rf");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) COMPONENT_REF
]) = 1;
ansi_opname
[(int) MEMBER_REF
] = get_identifier ("__rm");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MEMBER_REF
]) = 1;
ansi_opname
[(int) CALL_EXPR
] = get_identifier ("__cl");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) CALL_EXPR
]) = 1;
ansi_opname
[(int) ARRAY_REF
] = get_identifier ("__vc");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) ARRAY_REF
]) = 1;
ansi_opname
[(int) NEW_EXPR
] = get_identifier ("__nw");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) NEW_EXPR
]) = 1;
ansi_opname
[(int) DELETE_EXPR
] = get_identifier ("__dl");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) DELETE_EXPR
]) = 1;
ansi_opname
[(int) TYPE_EXPR
] = get_identifier ("__op");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) TYPE_EXPR
]) = 1;
/* This is not true: these operators are not defined in ANSI,
but we need them anyway. */
ansi_opname
[(int) MIN_EXPR
] = get_identifier ("__mn");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MIN_EXPR
]) = 1;
ansi_opname
[(int) MAX_EXPR
] = get_identifier ("__mx");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) MAX_EXPR
]) = 1;
ansi_opname
[(int) COND_EXPR
] = get_identifier ("__cn");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) COND_EXPR
]) = 1;
ansi_opname
[(int) METHOD_CALL_EXPR
] = get_identifier ("__wr");
IDENTIFIER_OPNAME_P (ansi_opname
[(int) METHOD_CALL_EXPR
]) = 1;
gcc_obstack_init (&inline_text_obstack
);
inline_text_firstobj
= (char *) obstack_alloc (&inline_text_obstack
, 0);
/* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */
current_function_decl
= NULL
;
token_buffer
= (char *) xmalloc (maxtoken
+ 2);
ridpointers
[(int) RID_INT
] = get_identifier ("int");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_INT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_INT
]));
ridpointers
[(int) RID_CHAR
] = get_identifier ("char");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_CHAR
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_CHAR
]));
ridpointers
[(int) RID_VOID
] = get_identifier ("void");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VOID
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VOID
]));
ridpointers
[(int) RID_FLOAT
] = get_identifier ("float");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_FLOAT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_FLOAT
]));
ridpointers
[(int) RID_DOUBLE
] = get_identifier ("double");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_DOUBLE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_DOUBLE
]));
ridpointers
[(int) RID_SHORT
] = get_identifier ("short");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_SHORT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_SHORT
]));
ridpointers
[(int) RID_LONG
] = get_identifier ("long");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_LONG
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_LONG
]));
ridpointers
[(int) RID_UNSIGNED
] = get_identifier ("unsigned");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_UNSIGNED
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_UNSIGNED
]));
ridpointers
[(int) RID_SIGNED
] = get_identifier ("signed");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_SIGNED
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_SIGNED
]));
ridpointers
[(int) RID_INLINE
] = get_identifier ("inline");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_INLINE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_INLINE
]));
ridpointers
[(int) RID_CONST
] = get_identifier ("const");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_CONST
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_CONST
]));
ridpointers
[(int) RID_VOLATILE
] = get_identifier ("volatile");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VOLATILE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VOLATILE
]));
ridpointers
[(int) RID_AUTO
] = get_identifier ("auto");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_AUTO
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_AUTO
]));
ridpointers
[(int) RID_STATIC
] = get_identifier ("static");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_STATIC
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_STATIC
]));
ridpointers
[(int) RID_EXTERN
] = get_identifier ("extern");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_EXTERN
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_EXTERN
]));
ridpointers
[(int) RID_TYPEDEF
] = get_identifier ("typedef");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_TYPEDEF
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_TYPEDEF
]));
ridpointers
[(int) RID_REGISTER
] = get_identifier ("register");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_REGISTER
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_REGISTER
]));
/* C++ extensions. These are probably not correctly named. */
ridpointers
[(int) RID_WCHAR
] = get_identifier ("__wchar_t");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_WCHAR
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_WCHAR
]));
class_type_node
= build_int_2 (class_type
, 0);
TREE_TYPE (class_type_node
) = class_type_node
;
ridpointers
[(int) RID_CLASS
] = class_type_node
;
record_type_node
= build_int_2 (record_type
, 0);
TREE_TYPE (record_type_node
) = record_type_node
;
ridpointers
[(int) RID_RECORD
] = record_type_node
;
union_type_node
= build_int_2 (union_type
, 0);
TREE_TYPE (union_type_node
) = union_type_node
;
ridpointers
[(int) RID_UNION
] = union_type_node
;
enum_type_node
= build_int_2 (enum_type
, 0);
TREE_TYPE (enum_type_node
) = enum_type_node
;
ridpointers
[(int) RID_ENUM
] = enum_type_node
;
ridpointers
[(int) RID_VIRTUAL
] = get_identifier ("virtual");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VIRTUAL
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VIRTUAL
]));
ridpointers
[(int) RID_FRIEND
] = get_identifier ("friend");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_FRIEND
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_FRIEND
]));
ridpointers
[(int) RID_PUBLIC
] = get_identifier ("public");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_PUBLIC
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_PUBLIC
]));
ridpointers
[(int) RID_PRIVATE
] = get_identifier ("private");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_PRIVATE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_PRIVATE
]));
ridpointers
[(int) RID_PROTECTED
] = get_identifier ("protected");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_PROTECTED
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_PROTECTED
]));
/* Exception handling extensions. */
exception_type_node
= build_int_2 (exception_type
, 0);
TREE_TYPE (exception_type_node
) = exception_type_node
;
ridpointers
[(int) RID_EXCEPTION
] = exception_type_node
;
opname_tab
[(int) COMPONENT_REF
] = "->";
opname_tab
[(int) MEMBER_REF
] = "->*";
opname_tab
[(int) METHOD_CALL_EXPR
] = "->()";
opname_tab
[(int) INDIRECT_REF
] = "(unary *)";
opname_tab
[(int) ARRAY_REF
] = "[]";
opname_tab
[(int) MODIFY_EXPR
] = "=";
opname_tab
[(int) NEW_EXPR
] = "new";
opname_tab
[(int) DELETE_EXPR
] = "delete";
opname_tab
[(int) COND_EXPR
] = "... ? ... : ...";
opname_tab
[(int) CALL_EXPR
] = "()";
opname_tab
[(int) PLUS_EXPR
] = "+";
opname_tab
[(int) MINUS_EXPR
] = "-";
opname_tab
[(int) MULT_EXPR
] = "*";
opname_tab
[(int) TRUNC_DIV_EXPR
] = "/";
opname_tab
[(int) CEIL_DIV_EXPR
] = "(ceiling /)";
opname_tab
[(int) FLOOR_DIV_EXPR
] = "(floor /)";
opname_tab
[(int) ROUND_DIV_EXPR
] = "(round /)";
opname_tab
[(int) TRUNC_MOD_EXPR
] = "%";
opname_tab
[(int) CEIL_MOD_EXPR
] = "(ceiling %)";
opname_tab
[(int) FLOOR_MOD_EXPR
] = "(floor %)";
opname_tab
[(int) ROUND_MOD_EXPR
] = "(round %)";
opname_tab
[(int) NEGATE_EXPR
] = "-";
opname_tab
[(int) MIN_EXPR
] = "<?";
opname_tab
[(int) MAX_EXPR
] = ">?";
opname_tab
[(int) ABS_EXPR
] = "abs";
opname_tab
[(int) FFS_EXPR
] = "ffs";
opname_tab
[(int) LSHIFT_EXPR
] = "<<";
opname_tab
[(int) RSHIFT_EXPR
] = ">>";
opname_tab
[(int) BIT_IOR_EXPR
] = "|";
opname_tab
[(int) BIT_XOR_EXPR
] = "^";
opname_tab
[(int) BIT_AND_EXPR
] = "&";
opname_tab
[(int) BIT_ANDTC_EXPR
] = "&~";
opname_tab
[(int) BIT_NOT_EXPR
] = "~";
opname_tab
[(int) TRUTH_ANDIF_EXPR
] = "&&";
opname_tab
[(int) TRUTH_ORIF_EXPR
] = "||";
opname_tab
[(int) TRUTH_AND_EXPR
] = "strict &&";
opname_tab
[(int) TRUTH_OR_EXPR
] = "strict ||";
opname_tab
[(int) TRUTH_NOT_EXPR
] = "!";
opname_tab
[(int) LT_EXPR
] = "<";
opname_tab
[(int) LE_EXPR
] = "<=";
opname_tab
[(int) GT_EXPR
] = ">";
opname_tab
[(int) GE_EXPR
] = ">=";
opname_tab
[(int) EQ_EXPR
] = "==";
opname_tab
[(int) NE_EXPR
] = "!=";
opname_tab
[(int) IN_EXPR
] = "in";
opname_tab
[(int) SET_LE_EXPR
] = "subset";
opname_tab
[(int) CARD_EXPR
] = "#";
opname_tab
[(int) RANGE_EXPR
] = "..";
opname_tab
[(int) CONVERT_EXPR
] = "(unary +)";
opname_tab
[(int) ADDR_EXPR
] = "(unary &)";
opname_tab
[(int) PREDECREMENT_EXPR
] = "--";
opname_tab
[(int) PREINCREMENT_EXPR
] = "++";
opname_tab
[(int) POSTDECREMENT_EXPR
] = "--";
opname_tab
[(int) POSTINCREMENT_EXPR
] = "++";
opname_tab
[(int) COMPOUND_EXPR
] = ",";
assignop_tab
[(int) NOP_EXPR
] = "=";
assignop_tab
[(int) PLUS_EXPR
] = "+=";
assignop_tab
[(int) CONVERT_EXPR
] = "+=";
assignop_tab
[(int) MINUS_EXPR
] = "-=";
assignop_tab
[(int) NEGATE_EXPR
] = "-=";
assignop_tab
[(int) MULT_EXPR
] = "*=";
assignop_tab
[(int) INDIRECT_REF
] = "*=";
assignop_tab
[(int) TRUNC_DIV_EXPR
] = "/=";
assignop_tab
[(int) EXACT_DIV_EXPR
] = "(exact /=)";
assignop_tab
[(int) CEIL_DIV_EXPR
] = "(ceiling /=)";
assignop_tab
[(int) FLOOR_DIV_EXPR
] = "(floor /=)";
assignop_tab
[(int) ROUND_DIV_EXPR
] = "(round /=)";
assignop_tab
[(int) TRUNC_MOD_EXPR
] = "%=";
assignop_tab
[(int) CEIL_MOD_EXPR
] = "(ceiling %=)";
assignop_tab
[(int) FLOOR_MOD_EXPR
] = "(floor %=)";
assignop_tab
[(int) ROUND_MOD_EXPR
] = "(round %=)";
assignop_tab
[(int) MIN_EXPR
] = "<?=";
assignop_tab
[(int) MAX_EXPR
] = ">?=";
assignop_tab
[(int) LSHIFT_EXPR
] = "<<=";
assignop_tab
[(int) RSHIFT_EXPR
] = ">>=";
assignop_tab
[(int) BIT_IOR_EXPR
] = "|=";
assignop_tab
[(int) BIT_XOR_EXPR
] = "^=";
assignop_tab
[(int) BIT_AND_EXPR
] = "&=";
assignop_tab
[(int) ADDR_EXPR
] = "&=";
#define UNSET_RESERVED_WORD(STRING) \
do { is_reserved_word (STRING, sizeof (STRING) - 1)->name = ""; } while (0)
if (flag_ansi_exceptions
)
flag_handle_exceptions
= 2;
if (!flag_ansi_exceptions
)
UNSET_RESERVED_WORD ("catch");
if (! flag_handle_exceptions
)
/* Easiest way to not recognize exception
handling extensions... */
UNSET_RESERVED_WORD ("all");
UNSET_RESERVED_WORD ("except");
UNSET_RESERVED_WORD ("exception");
UNSET_RESERVED_WORD ("raise");
UNSET_RESERVED_WORD ("raises");
UNSET_RESERVED_WORD ("reraise");
UNSET_RESERVED_WORD ("try");
UNSET_RESERVED_WORD ("throw");
else if (flag_ansi_exceptions
)
/* Easiest way to not recognize exception
handling extensions... */
UNSET_RESERVED_WORD ("exception");
UNSET_RESERVED_WORD ("all");
UNSET_RESERVED_WORD ("except");
UNSET_RESERVED_WORD ("raise");
UNSET_RESERVED_WORD ("raises");
UNSET_RESERVED_WORD ("reraise");
is_reserved_word ("try", sizeof ("try") - 1)->token
= ANSI_TRY
;
is_reserved_word ("throw", sizeof ("throw") - 1)->token
= ANSI_THROW
;
if (! (flag_gc
|| flag_dossier
))
UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof");
UNSET_RESERVED_WORD ("asm");
if (flag_no_asm
|| flag_traditional
)
UNSET_RESERVED_WORD ("typeof");
UNSET_RESERVED_WORD ("dynamic");
token_count
= init_parse ();
reinit_parse_for_function ()
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
yyprint (file
, yychar
, yylval
)
my_friendly_assert (TREE_CODE (t
) == IDENTIFIER_NODE
, 224);
if (IDENTIFIER_POINTER (t
))
fprintf (file
, " `%s'", IDENTIFIER_POINTER (t
));
if (yylval
.ttype
== class_type_node
)
fprintf (file
, " `class'");
else if (yylval
.ttype
== record_type_node
)
fprintf (file
, " `struct'");
else if (yylval
.ttype
== union_type_node
)
fprintf (file
, " `union'");
else if (yylval
.ttype
== enum_type_node
)
fprintf (file
, " `enum'");
case PRE_PARSED_CLASS_DECL
:
my_friendly_assert (TREE_CODE (t
) == TREE_LIST
, 225);
static int *reduce_count
;
#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
reduce_count
= (int *)malloc (sizeof (int) * (REDUCE_LENGTH
+ 1));
bzero (reduce_count
, sizeof (int) * (REDUCE_LENGTH
+ 1));
token_count
= (int *)malloc (sizeof (int) * (TOKEN_LENGTH
+ 1));
bzero (token_count
, sizeof (int) * (TOKEN_LENGTH
+ 1));
return reduce_count
[*q
] - reduce_count
[*p
];
return token_count
[*q
] - token_count
[*p
];
print_parse_statistics ()
int maxlen
= REDUCE_LENGTH
;
if (reduce_count
[-1] == 0)
if (TOKEN_LENGTH
> REDUCE_LENGTH
)
sorted
= (unsigned *) alloca (sizeof (int) * maxlen
);
for (i
= 0; i
< TOKEN_LENGTH
; i
++)
qsort (sorted
, TOKEN_LENGTH
, sizeof (int), token_cmp
);
for (i
= 0; i
< TOKEN_LENGTH
; i
++)
if (token_count
[index
] == 0)
if (token_count
[index
] < token_count
[-1])
fprintf (stderr
, "token %d, `%s', count = %d\n",
index
, yytname
[YYTRANSLATE (index
)], token_count
[index
]);
for (i
= 0; i
< REDUCE_LENGTH
; i
++)
qsort (sorted
, REDUCE_LENGTH
, sizeof (int), reduce_cmp
);
for (i
= 0; i
< REDUCE_LENGTH
; i
++)
if (reduce_count
[index
] == 0)
if (reduce_count
[index
] < reduce_count
[-1])
fprintf (stderr
, "rule %d, line %d, count = %d\n",
index
, yyrline
[index
], reduce_count
[index
]);
/* Sets the value of the 'yydebug' variable to VALUE.
This is a function so we don't have to have YYDEBUG defined
in order to build the compiler. */
warning ("YYDEBUG not defined.");
debug_yytranslate (value
)
return yytname
[YYTRANSLATE (value
)];
/* Functions and data structures for #pragma interface.
`#pragma implementation' means that the main file being compiled
is considered to implement (provide) the classes that appear in
its main body. I.e., if this is file "foo.cc", and class `bar'
is defined in "foo.cc", then we say that "foo.cc implements bar".
All main input files "implement" themselves automagically.
`#pragma interface' means that unless this file (of the form "foo.h"
is not presently being included by file "foo.cc", the
CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none
of the vtables nor any of the inline functions defined in foo.h
There are cases when we want to link files such as "defs.h" and
"main.cc". In this case, we give "defs.h" a `#pragma interface',
and "main.cc" has `#pragma implementation "defs.h"'. */
static struct impl_files
*impl_file_chain
;
/* Helper function to load global variables with interface
extract_interface_info ()
tree fileinfo
= get_time_identifier (input_filename
);
fileinfo
= IDENTIFIER_CLASS_VALUE (fileinfo
);
interface_only
= TREE_INT_CST_LOW (fileinfo
);
interface_unknown
= TREE_INT_CST_HIGH (fileinfo
);
/* Return nonzero if S and T are not considered part of an
INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
/* Set the interface/implementation bits for this scope. */
struct impl_files
*ifiles
;
s
= FILE_NAME_NONDIRECTORY (s
);
for (ifiles
= impl_file_chain
; ifiles
; ifiles
= ifiles
->next
)
char *t1
= ifiles
->filename
;
if (*s1
!= *t1
|| *s1
== 0)
while (*s1
== *t1
&& *s1
!= 0)
/* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */
if (index (s1
, '.') || index (t1
, '.'))
if (*s1
== '\0' || s1
[-1] != '.' || t1
[-1] != '.')
set_typedecl_interface_info (prev
, vars
)
tree id
= get_time_identifier (DECL_SOURCE_FILE (vars
));
tree fileinfo
= IDENTIFIER_CLASS_VALUE (id
);
tree type
= TREE_TYPE (vars
);
CLASSTYPE_INTERFACE_ONLY (type
) = TREE_INT_CST_LOW (fileinfo
)
= interface_strcmp (DECL_SOURCE_FILE (vars
));
set_vardecl_interface_info (prev
, vars
)
tree type
= DECL_CONTEXT (vars
);
if (CLASSTYPE_INTERFACE_UNKNOWN (type
) == 0)
if (CLASSTYPE_INTERFACE_ONLY (type
))
set_typedecl_interface_info (prev
, TYPE_NAME (type
));
CLASSTYPE_VTABLE_NEEDS_WRITING (type
) = 1;
DECL_EXTERNAL (vars
) = CLASSTYPE_INTERFACE_ONLY (type
);
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. */
struct pending_inline
*prev
= 0, *tail
;
struct pending_inline
*t
;
/* Reverse the pending inline functions, since
they were cons'd instead of appended. */
for (t
= pending_inlines
; t
; t
= tail
)
/* Reset to zero so that if the inline functions we are currently
processing define inline functions of their own, that is handled
correctly. ??? This hasn't been checked in a while. */
/* Now start processing the first inline function. */
my_friendly_assert ((t
->parm_vec
== NULL_TREE
) == (t
->bindings
== NULL_TREE
),
push_template_decls (t
->parm_vec
, t
->bindings
, 0);
feed_input (t
->buf
, t
->len
, t
->can_free
? &inline_text_obstack
: 0);
if (input_filename
!= t
->filename
)
input_filename
= t
->filename
;
/* Get interface/implementation back in sync. */
extract_interface_info ();
input_filename
= t
->filename
;
interface_unknown
= t
->interface
== 1;
interface_only
= t
->interface
== 0;
yychar
= PRE_PARSED_FUNCTION_DECL
;
/* Pass back a handle on the rest of the inline functions, so that they
can be processed later. */
yylval
.ttype
= build_tree_list ((tree
) t
, t
->fndecl
);
if (flag_default_inline
&& t
->fndecl
/* If we're working from a template, don't change
&& t
->parm_vec
== NULL_TREE
)
DECL_INLINE (t
->fndecl
) = 1;
DECL_PENDING_INLINE_INFO (t
->fndecl
) = 0;
extern struct pending_input
*to_be_restored
;
static int nextchar
= -1;
struct pending_inline
*i
= (struct pending_inline
*) TREE_PURPOSE (t
);
my_friendly_assert ((i
->parm_vec
== NULL_TREE
) == (i
->bindings
== NULL_TREE
),
pop_template_decls (i
->parm_vec
, i
->bindings
, 0);
if (yychar
!= END_OF_SAVED_INPUT
)
error ("parse error at end of saved function text");
/* restore_pending_input will abort unless yychar is either
* END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
* hosed, feed back YYEMPTY.
* We also need to discard nextchar, since that may have gotten
restore_pending_input (to_be_restored
);
if (i
&& i
->fndecl
!= NULL_TREE
)
my_friendly_assert ((i
->parm_vec
== NULL_TREE
) == (i
->bindings
== NULL_TREE
),
push_template_decls (i
->parm_vec
, i
->bindings
, 0);
feed_input (i
->buf
, i
->len
, i
->can_free
? &inline_text_obstack
: 0);
input_filename
= i
->filename
;
yychar
= PRE_PARSED_FUNCTION_DECL
;
yylval
.ttype
= build_tree_list ((tree
) i
, i
->fndecl
);
/* If we're working from a template, don't change
&& i
->parm_vec
== NULL_TREE
)
DECL_INLINE (i
->fndecl
) = 1;
DECL_PENDING_INLINE_INFO (i
->fndecl
) = 0;
interface_unknown
= i
->interface
== 1;
interface_only
= i
->interface
== 0;
extract_interface_info ();
/* Since inline methods can refer to text which has not yet been seen,
we store the text of the method in a structure which is placed in the
DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
After parsing the body of the class definition, the FUNCTION_DECL's are
scanned to see which ones have this field set. Those are then digested
This function's FUNCTION_DECL will have a bit set in its common so
that we know to watch out for it. */
consume_string (this_obstack
)
register struct obstack
*this_obstack
;
obstack_1grow (this_obstack
, c
);
obstack_1grow (this_obstack
, c
);
pedwarn ("ANSI C++ forbids newline in string constant");
obstack_1grow (this_obstack
, c
);
static int nextyychar
= YYEMPTY
;
static YYSTYPE nextyylval
;
int nextchar
, yychar
, nextyychar
, eof
;
YYSTYPE yylval
, nextyylval
;
struct obstack token_obstack
;
p
= (struct pending_input
*) xmalloc (sizeof (struct pending_input
));
p
->nextyychar
= nextyychar
;
p
->nextyylval
= nextyylval
;
yychar
= nextyychar
= YYEMPTY
;
p
->first_token
= first_token
;
p
->token_obstack
= token_obstack
;
gcc_obstack_init (&token_obstack
);
restore_pending_input (p
)
my_friendly_assert (nextchar
== -1, 229);
my_friendly_assert (yychar
== YYEMPTY
|| yychar
== END_OF_SAVED_INPUT
, 230);
my_friendly_assert (nextyychar
== YYEMPTY
, 231);
nextyychar
= p
->nextyychar
;
nextyylval
= p
->nextyylval
;
first_token
= p
->first_token
;
obstack_free (&token_obstack
, (char *) 0);
token_obstack
= p
->token_obstack
;
/* Return next non-whitespace input character, which may come
from `finput', or from `nextchar'. */
return skip_white_space (c
);
/* Unget character CH from the input stream.
If RESCAN is non-zero, then we want to `see' this
character as the next input token. */
/* Unget a character from the input stream. */
if (yychar
== YYEMPTY
|| rescan
== 0)
my_friendly_assert (nextyychar
== YYEMPTY
, 232);
/* This function stores away the text for an inline function that should
be processed later. It decides how much later, and may need to move
the info between obstacks; therefore, the caller should not refer to
the T parameter after calling this function.
This function also stores the list of template-parameter bindings that
will be needed for expanding the template, if any. */
store_pending_inline (decl
, t
)
struct pending_inline
*t
;
extern int processing_template_defn
;
struct pending_inline
**inlines
;
/* Default: compile right away, and no extra bindings are needed. */
t
->parm_vec
= t
->bindings
= 0;
if (processing_template_defn
)
tree type
= current_class_type
;
/* Assumption: In this (possibly) nested class sequence, only
one name will have template parms. */
while (type
&& TREE_CODE_CLASS (TREE_CODE (type
)) == 't')
tree decl
= TYPE_NAME (type
);
tree tmpl
= IDENTIFIER_TEMPLATE (DECL_NAME (decl
));
t
->parm_vec
= DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl
))->parm_vec
;
t
->bindings
= TREE_VALUE (tmpl
);
type
= DECL_CONTEXT (decl
);
if (TREE_CODE (TREE_TYPE (decl
)) == METHOD_TYPE
|| TREE_CODE (TREE_TYPE (decl
)) == FUNCTION_TYPE
)
if (TREE_CODE (TREE_TYPE (decl
)) == METHOD_TYPE
)
my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl
)) == current_class_type
,
/* Inline functions can be compiled immediately. Other functions
will be output separately, so if we're in interface-only mode,
punt them now, or output them now if we're doing implementations
and we know no overrides will exist. Otherwise, we delay until
end-of-file, to see if the definition is really required. */
else if (current_class_type
&& !interface_unknown
)
print_node_brief (stderr
, "\ndiscarding text for ", decl
, 0);
obstack_free (&inline_text_obstack
, t
->buf
);
DECL_PENDING_INLINE_INFO (decl
) = 0;
/* Don't delay the processing of virtual functions. */
else if (DECL_VINDEX (decl
) == NULL_TREE
)
extern struct pending_inline
*pending_template_expansions
;
t
->buf
= (char *) obstack_copy (&permanent_obstack
, t
->buf
,
t
= (struct pending_inline
*) obstack_copy (&permanent_obstack
,
obstack_free (&inline_text_obstack
, free_to
);
inlines
= &pending_template_expansions
;
inlines
= &pending_inlines
;
DECL_PENDING_INLINE_INFO (decl
) = t
;
/* Because we use obstacks, we must process these in precise order. */
void reinit_parse_for_block ();
reinit_parse_for_method (yychar
, decl
)
int starting_lineno
= lineno
;
char *starting_filename
= input_filename
;
reinit_parse_for_block (yychar
, &inline_text_obstack
, 0);
len
= obstack_object_size (&inline_text_obstack
);
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
if (decl
== void_type_node
|| (current_class_type
&& TYPE_REDEFINED (current_class_type
)))
/* Happens when we get two declarations of the same
function in the same scope. */
char *buf
= obstack_finish (&inline_text_obstack
);
obstack_free (&inline_text_obstack
, buf
);
struct pending_inline
*t
;
char *buf
= obstack_finish (&inline_text_obstack
);
t
= (struct pending_inline
*) obstack_alloc (&inline_text_obstack
,
sizeof (struct pending_inline
));
t
->lineno
= starting_lineno
;
t
->filename
= starting_filename
;
t
->interface
= ((interface_unknown
|| processing_template_defn
)
: (interface_only
? 0 : 2));
store_pending_inline (decl
, t
);
/* Consume a block -- actually, a method or template definition beginning
with `:' or `{' -- and save it away on the specified obstack.
Argument IS_TEMPLATE indicates which set of error messages should be
output if something goes wrong. This should really be cleaned up somehow,
without loss of clarity. */
reinit_parse_for_block (yychar
, obstackp
, is_template
)
struct obstack
*obstackp
;
int starting_lineno
= lineno
;
char *starting_filename
= input_filename
;
int look_for_semicolon
= 0;
obstack_1grow (obstackp
, '{');
if (yychar
!= ':' && (yychar
!= RETURN
|| is_template
))
? "parse error in template specification"
: "parse error in method specification");
obstack_1grow (obstackp
, yychar
);
int this_lineno
= lineno
;
/* Don't lose our cool if there are lots of comments. */
if (lineno
== this_lineno
)
else if (lineno
- this_lineno
< 10 /* + strlen (input_filename) */)
for (i
= lineno
- this_lineno
; i
> 0; i
--)
obstack_1grow (obstackp
, '\n');
sprintf (buf
, "\n# %d \"", lineno
);
obstack_grow (obstackp
, buf
, len
);
len
= strlen (input_filename
);
obstack_grow (obstackp
, input_filename
, len
);
obstack_1grow (obstackp
, '\"');
obstack_1grow (obstackp
, '\n');
/* strings must be read differently than text. */
obstack_1grow (obstackp
, c
);
consume_string (obstackp
);
while (c
> ' ') /* ASCII dependent! */
obstack_1grow (obstackp
, c
);
if (c
== '{') goto main_loop
;
consume_string (obstackp
);
? "template body missing"
: "function body for constructor missing");
obstack_1grow (obstackp
, '{');
obstack_1grow (obstackp
, '}');
obstack_1grow (obstackp
, c
);
error_with_file_and_line (starting_filename
,
"end of file read inside definition");
int this_lineno
= lineno
;
c
= skip_white_space (getch ());
/* Don't lose our cool if there are lots of comments. */
if (lineno
- this_lineno
)
if (lineno
- this_lineno
== 1)
obstack_1grow (obstackp
, '\n');
sprintf (buf
, "\n# %d \"", lineno
);
obstack_grow (obstackp
, buf
, len
);
len
= strlen (input_filename
);
obstack_grow (obstackp
, input_filename
, len
);
obstack_1grow (obstackp
, '\"');
obstack_1grow (obstackp
, '\n');
obstack_1grow (obstackp
, c
);
if (blev
== 0 && !look_for_semicolon
)
consume_string (obstackp
);
else if (c
== ';' && look_for_semicolon
&& blev
== 0)
obstack_1grow (obstackp
, c
);
obstack_1grow (obstackp
, '\0');
/* Build a default function named NAME for type TYPE.
When KIND == 0, build default destructor.
When KIND == 1, build virtual destructor.
When KIND == 2, build default constructor.
When KIND == 3, build default X(const X&) constructor.
When KIND == 4, build default X(X&) constructor. */
cons_up_default_function (type
, name
, kind
)
extern tree void_list_node
, constructor_name ();
tree declspecs
= NULL_TREE
;
name
= constructor_name (name
);
declspecs
= build_decl_list (NULL_TREE
, ridpointers
[(int) RID_VIRTUAL
]);
name
= build_parse_node (BIT_NOT_EXPR
, name
);
/* Default constructor. */
type
= build_type_variant (type
, 1, 0);
argtype
= build_reference_type (type
);
args
= tree_cons (NULL_TREE
,
build_tree_list (hash_tree_chain (argtype
, NULL_TREE
),
fn
= start_method (declspecs
,
build_parse_node (CALL_EXPR
, name
, args
, NULL_TREE
),
if (fn
== void_type_node
)
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
struct pending_inline
*t
;
t
= (struct pending_inline
*) obstack_alloc (&inline_text_obstack
,
sizeof (struct pending_inline
));
t
->filename
= input_filename
;
t
->interface
= ((interface_unknown
|| processing_template_defn
)
: (interface_only
? 0 : 2));
store_pending_inline (fn
, t
);
/* We make this declaration private (static in the C sense). */
DECL_CLASS_CONTEXT (fn
) = type
;
/* Show that this function was generated by the compiler. */
DECL_SOURCE_LINE (fn
) = 0;
/* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message
if we know the user has blown it. */
check_for_missing_semicolon (type
)
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type
)))
error ("semicolon missing after %s declaration",
TREE_CODE (type
) == ENUMERAL_TYPE
? "enum" : "struct");
error ("semicolon missing after declaration of `%s'",
TYPE_NAME_STRING (type
));
shadow_tag (build_tree_list (0, type
));
/* Could probably also hack cases where class { ... } f (); appears. */
note_got_semicolon (type
)
if (TREE_CODE_CLASS (TREE_CODE (type
)) != 't')
CLASSTYPE_GOT_SEMICOLON (type
) = 1;
note_list_got_semicolon (declspecs
)
for (link
= declspecs
; link
; link
= TREE_CHAIN (link
))
tree type
= TREE_VALUE (link
);
if (TREE_CODE_CLASS (TREE_CODE (type
)) == 't')
note_got_semicolon (type
);
/* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */
while (c
== ' ' || c
== '\t');
error ("stray '\\' in program");
/* Make the token buffer longer, preserving the data in it.
P should point to just beyond the last valid character in the old buffer.
The value we return is a pointer to the new buffer
at a place corresponding to P. */
int offset
= p
- token_buffer
;
maxtoken
= maxtoken
* 2 + 10;
token_buffer
= (char *) xrealloc (token_buffer
, maxtoken
+ 2);
return token_buffer
+ offset
;
get_last_nonwhite_on_line ()
/* Is this the last nonwhite stuff on the line? */
c
= nextchar
, nextchar
= -1;
while (c
== ' ' || c
== '\t')
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
Otherwise, return the line's first non-whitespace character. */
/* Read first nonwhite char on the line. */
while (c
== ' ' || c
== '\t');
/* If not #, return it so caller will use it. */
/* Read first nonwhite char after the `#'. */
while (c
== ' ' || c
== '\t');
/* If a letter follows, then if the word here is `line', skip
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
if ((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'))
/* Read first nonwhite char after the `#pragma'. */
while (c
== ' ' || c
== '\t');
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
extern tree pending_vtables
;
/* More follows: it must be a string constant (class name). */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #pragma vtable");
warning ("use `+e2' option to enable #pragma vtable");
pending_vtables
= perm_tree_cons (NULL_TREE
, get_identifier (TREE_STRING_POINTER (yylval
.ttype
)), pending_vtables
);
warning ("trailing characters ignored");
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
/* More follows: it must be a string constant (unit name). */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #pragma unit");
current_unit_name
= get_identifier (TREE_STRING_POINTER (yylval
.ttype
));
current_unit_language
= current_lang_name
;
warning ("trailing characters ignored");
tree fileinfo
= IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename
));
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
if (impl_file_chain
== 0)
/* If this is zero at this point, then we are
if (main_input_filename
== 0)
main_input_filename
= input_filename
;
filename
= FILE_NAME_NONDIRECTORY (main_input_filename
);
fi
= get_time_identifier (filename
);
fi
= IDENTIFIER_CLASS_VALUE (fi
);
TREE_INT_CST_LOW (fi
) = 0;
TREE_INT_CST_HIGH (fi
) = 1;
impl_file_chain
= (struct impl_files
*)permalloc (sizeof (struct impl_files
));
impl_file_chain
->filename
= filename
;
impl_file_chain
->next
= 0;
interface_only
= interface_strcmp (input_filename
);
TREE_INT_CST_LOW (fileinfo
) = interface_only
;
TREE_INT_CST_HIGH (fileinfo
) = interface_unknown
;
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
char *main_filename
= main_input_filename
? main_input_filename
: input_filename
;
while (c
== ' ' || c
== '\t')
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid `#pragma implementation'");
main_filename
= TREE_STRING_POINTER (yylval
.ttype
);
main_filename
= FILE_NAME_NONDIRECTORY (main_filename
);
struct impl_files
*ifiles
= impl_file_chain
;
if (! strcmp (ifiles
->filename
, main_filename
))
ifiles
= (struct impl_files
*) permalloc (sizeof (struct impl_files
));
ifiles
->filename
= main_filename
;
ifiles
->next
= impl_file_chain
;
impl_file_chain
= ifiles
;
else if ((main_input_filename
!= 0
&& ! strcmp (main_input_filename
, input_filename
))
|| ! strcmp (input_filename
, main_filename
))
if (impl_file_chain
== 0)
impl_file_chain
= (struct impl_files
*) permalloc (sizeof (struct impl_files
));
impl_file_chain
->filename
= main_filename
;
impl_file_chain
->next
= 0;
error ("`#pragma implementation' can only appear at top-level");
/* We make this non-zero so that we infer decl linkage
in the impl file only for variables first declared
in the interface file. */
TREE_INT_CST_LOW (fileinfo
) = interface_only
;
TREE_INT_CST_HIGH (fileinfo
) = interface_unknown
;
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
#ifdef DWARF_DEBUGGING_INFO
if ((debug_info_level
== DINFO_LEVEL_VERBOSE
)
&& (write_symbols
== DWARF_DEBUG
))
dwarfout_define (lineno
, get_directive_line (finput
));
#endif /* DWARF_DEBUGGING_INFO */
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
#ifdef DWARF_DEBUGGING_INFO
if ((debug_info_level
== DINFO_LEVEL_VERBOSE
)
&& (write_symbols
== DWARF_DEBUG
))
dwarfout_undef (lineno
, get_directive_line (finput
));
#endif /* DWARF_DEBUGGING_INFO */
&& ((c
= getch ()) == ' ' || c
== '\t'))
&& ((c
= getch ()) == ' ' || c
== '\t'))
extern FILE *asm_out_file
;
/* #ident. The pedantic warning is now in cccp.c. */
/* Here we have just seen `#ident '.
A string constant should follow. */
while (c
== ' ' || c
== '\t')
/* If no argument, ignore the line. */
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #ident");
ASM_OUTPUT_IDENT (asm_out_file
,
TREE_STRING_POINTER (yylval
.ttype
));
/* Skip the rest of this line. */
&& ((c
= getch ()) == ' ' || c
== '\t'))
/* Used to test incremental compilation. */
sorry ("#pragma newworld");
error ("undefined or invalid # directive");
/* Here we have either `#line' or `# <nonletter>'.
In either case, it should be a line number; a digit should follow. */
while (c
== ' ' || c
== '\t')
/* If the # is the only nonwhite char on the line,
just ignore it. Check the new newline. */
/* Something follows the #; read a token. */
&& TREE_CODE (yylval
.ttype
) == INTEGER_CST
)
/* subtract one, because it is the following line that
gets the specified number */
int l
= TREE_INT_CST_LOW (yylval
.ttype
) - 1;
c
= get_last_nonwhite_on_line ();
/* No more: store the line number and check following line. */
/* More follows: it must be a string constant (filename). */
/* Read the string constant, but don't treat \ as special. */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
/* Changing files again. This means currently collected time
is charged against header time, and body time starts back
if (flag_detailed_statistics
)
int this_time
= my_get_run_time ();
tree time_identifier
= get_time_identifier (TREE_STRING_POINTER (yylval
.ttype
));
header_time
+= this_time
- body_time
;
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
))
+= this_time
- body_time
;
this_filename_time
= time_identifier
;
= (char *) permalloc (TREE_STRING_LENGTH (yylval
.ttype
) + 1);
strcpy (input_filename
, TREE_STRING_POINTER (yylval
.ttype
));
GNU_xref_file (input_filename
);
/* Each change of file name
reinitializes whether we are now in a system header. */
if (main_input_filename
== 0)
struct impl_files
*ifiles
= impl_file_chain
;
ifiles
->filename
= FILE_NAME_NONDIRECTORY (input_filename
);
main_input_filename
= input_filename
;
walk_vtables (set_typedecl_interface_info
, set_vardecl_interface_info
);
extract_interface_info ();
c
= get_last_nonwhite_on_line ();
cadillac_switch_source (-1);
/* `1' after file name means entering new file.
`2' after file name means just left a file. */
&& TREE_CODE (yylval
.ttype
) == INTEGER_CST
)
if (TREE_INT_CST_LOW (yylval
.ttype
) == 1)
/* Pushing to a new file. */
= (struct file_stack
*) xmalloc (sizeof (struct file_stack
));
input_file_stack
->line
= old_lineno
;
p
->next
= input_file_stack
;
p
->name
= input_filename
;
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level
== DINFO_LEVEL_VERBOSE
&& write_symbols
== DWARF_DEBUG
)
dwarfout_start_new_source_file (input_filename
);
#endif /* DWARF_DEBUGGING_INFO */
else if (TREE_INT_CST_LOW (yylval
.ttype
) == 2)
/* Popping out of a file. */
if (input_file_stack
->next
)
struct file_stack
*p
= input_file_stack
;
input_file_stack
= p
->next
;
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level
== DINFO_LEVEL_VERBOSE
&& write_symbols
== DWARF_DEBUG
)
dwarfout_resume_previous_source_file (input_file_stack
->line
);
#endif /* DWARF_DEBUGGING_INFO */
error ("#-lines for entering and leaving files don't match");
cadillac_switch_source (-1);
/* If we have handled a `1' or a `2',
see if there is another number to read. */
c
= get_last_nonwhite_on_line ();
cadillac_switch_source (-1);
/* `3' after file name means this is a system header file. */
&& TREE_CODE (yylval
.ttype
) == INTEGER_CST
&& TREE_INT_CST_LOW (yylval
.ttype
) == 3)
/* If NEXTCHAR is not end of line, we don't care what it is. */
error ("invalid #-line");
/* skip the rest of this line. */
while ((c
= getch ()) != EOF
&& c
!= '\n');
#define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
#define isdigit(char) (char >= '0' && char <= '9')
#define ENDFILE -1 /* token that represents end-of-file */
/* Read an escape sequence, returning its equivalent as a character,
or store 1 in *ignore_ptr if it is backslash-newline. */
register int c
= getch ();
warning ("the meaning of `\\x' varies with -traditional");
if (c
>= 'a' && c
<= 'f')
if (c
>= 'A' && c
<= 'F')
if (c
>= '0' && c
<= '9')
if (code
!= 0 || count
!= 0)
error ("\\x used with no following hex digits");
/* Digits are all 0's. Ok. */
else if ((count
- 1) * 4 >= TYPE_PRECISION (integer_type_node
)
&& ((1 << (TYPE_PRECISION (integer_type_node
) - (count
- 1) * 4))
warning ("hex escape out of range");
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
while ((c
<= '7') && (c
>= '0') && (count
++ < 3))
code
= (code
* 8) + (c
- '0');
case '\\': case '\'': case '"':
warning ("the meaning of `\\a' varies with -traditional");
pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c
);
/* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
pedwarn ("unknown escape sequence `\\%c'", c
);
if (c
>= 040 && c
< 0177)
pedwarn ("unknown escape sequence `\\%c'", c
);
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c
);
/* Value is 1 if we should try to make the next identifier look like a
typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion.
Value is -1 if we must not see a type name. */
int looking_for_typename
= 0;
looking_for_typename
= -1;
if (yychar
== TYPENAME
|| yychar
== PTYPENAME
)
extern __inline
int identifier_type ();
if (TREE_CODE (decl
) == TEMPLATE_DECL
&& DECL_TEMPLATE_IS_CLASS (decl
))
if (TREE_CODE (decl
) != TYPE_DECL
)
looking_for_typename
= 0;
if (yychar
== IDENTIFIER
)
lastiddecl
= lookup_name (yylval
.ttype
, -1);
lastiddecl
= IDENTIFIER_LABEL_VALUE (yylval
.ttype
);
yychar
= identifier_type (lastiddecl
);
tree
do_identifier (token
)
register tree id
= lastiddecl
;
/* Scope class declarations before global
if (id
== IDENTIFIER_GLOBAL_VALUE (token
)
&& current_class_type
!= 0
&& TYPE_SIZE (current_class_type
) == 0
&& TREE_CODE (current_class_type
) != UNINSTANTIATED_P_TYPE
)
/* Could be from one of the base classes. */
tree field
= lookup_field (current_class_type
, token
, 1, 0);
else if (field
== error_mark_node
)
/* We have already generated the error message.
But we still want to return this value. */
id
= lookup_field (current_class_type
, token
, 0, 0);
else if (TREE_CODE (field
) == VAR_DECL
|| TREE_CODE (field
) == CONST_DECL
)
else if (TREE_CODE (field
) != FIELD_DECL
)
error_with_decl (field
, "invalid use of member `%s' from base class `%s'",
TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field
)));
if (!id
|| id
== error_mark_node
)
if (id
== error_mark_node
&& current_class_type
!= NULL_TREE
)
id
= lookup_nested_field (token
);
/* In lookup_nested_field(), we marked this so we can gracefully
leave this whole mess. */
if (id
&& id
!= error_mark_node
&& TREE_TYPE (id
) == error_mark_node
)
if (yychar
== '(' || yychar
== LEFT_RIGHT
)
id
= implicitly_declare (token
);
else if (current_function_decl
== 0)
error ("`%s' undeclared, outside of functions",
IDENTIFIER_POINTER (token
));
if (IDENTIFIER_GLOBAL_VALUE (token
) != error_mark_node
|| IDENTIFIER_ERROR_LOCUS (token
) != current_function_decl
)
extern int undeclared_variable_notice
;
error ("`%s' undeclared (first use this function)",
IDENTIFIER_POINTER (token
));
if (! undeclared_variable_notice
)
error ("(Each undeclared identifier is reported only once");
error ("for each function it appears in.)");
undeclared_variable_notice
= 1;
/* Prevent repeated error messages. */
IDENTIFIER_GLOBAL_VALUE (token
) = error_mark_node
;
SET_IDENTIFIER_ERROR_LOCUS (token
, current_function_decl
);
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id
) == CONST_DECL
)
if (IDENTIFIER_CLASS_VALUE (token
) == id
)
enum visibility_type visibility
= compute_visibility (TYPE_BINFO (current_class_type
), id
);
if (visibility
== visibility_private
)
error_with_decl (id
, "enum `%s' is private");
/* protected is OK, since it's an enum of `this'. */
else id
= hack_identifier (id
, token
, yychar
);
identifier_typedecl_value (node
)
type
= IDENTIFIER_TYPE_VALUE (node
);
if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
do (IDENTIFIER_LOCAL_VALUE (node
));
do (IDENTIFIER_CLASS_VALUE (node
));
do (IDENTIFIER_GLOBAL_VALUE (node
));
/* Will this one ever happen? */
struct try_type type_sequence
[] =
{ &integer_type_node
, 0, 0, 0},
{ &unsigned_type_node
, 1, 0, 0},
{ &long_integer_type_node
, 0, 1, 0},
{ &long_unsigned_type_node
, 1, 1, 0},
{ &long_long_integer_type_node
, 0, 1, 1},
{ &long_long_unsigned_type_node
, 1, 1, 1}
c
= nextchar
, nextchar
= -1;
/* Effectively do c = skip_white_space (c)
but do it faster in the usual cases. */
/* Call skip_white_space so we can warn if appropriate. */
c
= skip_white_space (c
);
/* yylloc.first_line = lineno; */
value
= END_OF_SAVED_INPUT
;
else if (do_pending_expansions ())
/* this will set yychar for us */
/* Capital L may start a wide-string or wide-character constant. */
register int c
= getch ();
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
/* We know that `token_buffer' can hold at least on char,
so we install C immediately.
We may have to read the value in `putback_char', so call
/* Make this run fast. We know that we are reading straight
from FINPUT in this case (since identifiers cannot straddle
while (isalnum (c
) || (c
== '_') || c
== '$')
if (p
>= token_buffer
+ maxtoken
)
p
= extend_token_buffer (p
);
if (c
== '$' && ! dollars_in_ident
)
/* We know that `token_buffer' can hold at least on char,
so we install C immediately. */
while (isalnum (c
) || (c
== '_') || c
== '$')
if (p
>= token_buffer
+ maxtoken
)
p
= extend_token_buffer (p
);
if (c
== '$' && ! dollars_in_ident
)
/* Try to recognize a keyword. Uses minimum-perfect hash function */
register struct resword
*ptr
;
if (ptr
= is_reserved_word (token_buffer
, p
- token_buffer
))
tree old_ttype
= ridpointers
[(int) ptr
->rid
];
/* If this provides a type for us, then revert lexical
state to standard state. */
if (TREE_CODE (old_ttype
) == IDENTIFIER_NODE
&& IDENTIFIER_GLOBAL_VALUE (old_ttype
) != 0
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype
)) == TYPE_DECL
)
looking_for_typename
= 0;
else if (ptr
->token
== AGGR
|| ptr
->token
== ENUM
)
looking_for_typename
= 1;
/* Check if this is a language-type declaration.
Just glimpse the next non-white character. */
nextchar
= skip_white_space (nextchar
);
/* We are looking at a string. Complain
if the token before the string is no `extern'.
Could cheat some memory by placing this string
on the temporary_, instead of the saveable_
if (ptr
->rid
!= RID_EXTERN
)
error ("invalid modifier `%s' for language string",
value
= EXTERN_LANG_STRING
;
yylval
.ttype
= get_identifier (TREE_STRING_POINTER (yylval
.ttype
));
if (ptr
->token
== VISSPEC
)
yylval
.itype
= visibility_public
;
yylval
.itype
= visibility_private
;
yylval
.itype
= visibility_protected
;
yylval
.ttype
= old_ttype
;
value
= (int) ptr
->token
;
/* If we did not find a keyword, look for an identifier
if (value
== IDENTIFIER
|| value
== TYPESPEC
)
GNU_xref_ref (current_function_decl
, token_buffer
);
tmp
= get_identifier (token_buffer
);
/* Make sure that user does not collide with our internal
|| DESTRUCTOR_NAME_P (tmp
)
|| ANON_PARMNAME_P (tmp
)))
warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
if (value
== NEW
&& ! global_bindings_p ())
looking_for_typename
= 1;
register int c1
= getch ();
goto resume_numerical_scan
;
/* Optimize for most frequent case. */
register int c1
= getch ();
if (! isalnum (c1
) && c1
!= '.')
yylval
.ttype
= integer_zero_node
;
yylval
.ttype
= integer_one_node
;
case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* for multi-precision arithmetic,
we store only 8 live bits in each short. */
short shorts
[MAX_SHORTS
];
enum anon1
{ NOT_FLOAT
, AFTER_POINT
, TOO_MANY_POINTS
} floatflag
for (count
= 0; count
< MAX_SHORTS
; count
++)
if ((c
== 'x') || (c
== 'X'))
/* Leading 0 forces octal unless the 0 is the only digit. */
else if (c
>= '0' && c
<= '9')
/* Read all the digits-and-decimal-points. */
|| (isalnum (c
) && (c
!= 'l') && (c
!= 'L')
&& (c
!= 'u') && (c
!= 'U')
&& (floatflag
== NOT_FLOAT
|| ((c
!= 'f') && (c
!= 'F')))))
error ("floating constant may not be in radix 16");
if (floatflag
== AFTER_POINT
)
error ("malformed floating constant");
floatflag
= TOO_MANY_POINTS
;
/* Accept '.' as the start of a floating-point number
only when it is followed by a digit.
Otherwise, unread the following non-digit
and use the '.' as a structural token. */
if (p
== token_buffer
+ 2 && !isdigit (c
))
/* It is not a decimal point.
It should be a digit (perhaps a hex digit). */
break; /* start of exponent */
error ("nondigits in number and not hexadecimal");
for (count
= 0; count
< MAX_SHORTS
; count
++)
shorts
[count
] += (shorts
[count
-1] >> 8);
shorts
[count
-1] &= (1<<8)-1;
if (shorts
[MAX_SHORTS
- 1] >= 1<<8
|| shorts
[MAX_SHORTS
- 1] < - (1 << 8))
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
error ("numeric constant with no digits");
if (largest_digit
>= base
)
error ("numeric constant contains digits beyond the radix");
/* Remove terminating char from the token buffer and delimit the string */
if (floatflag
!= NOT_FLOAT
)
tree type
= double_type_node
;
/* Read explicit exponent if any, and put it in tokenbuf. */
if ((c
== 'e') || (c
== 'E'))
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if ((c
== '+') || (c
== '-'))
error ("floating constant exponent has no digits");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
/* Convert string to a double, checking for overflow. */
error ("floating constant out of range");
set_float_handler (handler
);
value
= REAL_VALUE_ATOF (token_buffer
);
set_float_handler (NULL
);
if (errno
== ERANGE
&& !flag_traditional
)
/* Check for "0.0" and variants;
SunOS 4 spuriously returns ERANGE for them. */
if (*p1
== 'e' || *p1
== 'E')
/* with significand==0, ignore the exponent */
/* ERANGE is also reported for underflow,
so test the value to distinguish overflow from that. */
if (*p1
!= 0 && (value
> 1.0 || value
< -1.0))
warning ("floating point number exceeds range of `double'");
/* Read the suffixes to choose a data type. */
if (c
== 'f' || c
== 'F')
error ("two `f's in floating constant");
value
= real_value_truncate (TYPE_MODE (type
), value
);
else if (c
== 'l' || c
== 'L')
error ("two `l's in floating constant");
type
= long_double_type_node
;
error ("garbage at end of number");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
/* Create a node with determined type and value. */
yylval
.ttype
= build_real (type
, value
);
if (c
== 'u' || c
== 'U')
error ("two `u's in integer constant");
else if (c
== 'l' || c
== 'L')
error ("three `l's in integer constant");
pedwarn ("ANSI C++ forbids long long integer constants");
error ("garbage at end of number");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
/* ??? This code assumes that everything but long long is 32-bits.
Probably this code needs to be replaced with code similar
to that in c-lex.c, but I don't want to do it. -- RK. */
if ((overflow
|| shorts
[7] || shorts
[6] || shorts
[5] || shorts
[4])
warning ("integer constant out of range");
/* If it won't fit in a signed long long, make it unsigned.
We can't distinguish based on the tree node because
any integer constant fits any long long type. */
/* This is simplified by the fact that our constant
for (i
= 0; i
< MAX_SHORTS
/ 2; i
++)
high
|= (HOST_WIDE_INT
) shorts
[i
+ MAX_SHORTS
/ 2] << (i
* 8);
low
|= (HOST_WIDE_INT
) shorts
[i
] << (i
* 8);
yylval
.ttype
= build_int_2 (low
, high
);
/* Find the first allowable type that the value fits in. */
for (i
= 0; i
< sizeof (type_sequence
) / sizeof (type_sequence
[0]);
if (!(spec_long
&& !type_sequence
[i
].long_flag
)
&& !(spec_long_long
&& !type_sequence
[i
].long_long_flag
)
&& !(spec_unsigned
&& !type_sequence
[i
].unsigned_flag
)
/* A hex or octal constant traditionally is unsigned. */
&& !(base
!= 10 && flag_traditional
&& !type_sequence
[i
].unsigned_flag
)
/* A decimal constant can't be unsigned int
unless explicitly specified. */
&& !(base
== 10 && !spec_unsigned
&& *type_sequence
[i
].node_var
== unsigned_type_node
))
if (int_fits_type_p (yylval
.ttype
, *type_sequence
[i
].node_var
))
type
= *type_sequence
[i
].node_var
;
if (flag_traditional
&& type
== long_unsigned_type_node
type
= long_integer_type_node
;
type
= long_long_integer_type_node
;
warning ("integer constant out of range");
/* Warn about some cases where the type of a given constant
changes from traditional C to ANSI C. */
/* This computation is the same as the previous one
except that flag_traditional is used backwards. */
for (i
= 0; i
< sizeof (type_sequence
) / sizeof (type_sequence
[0]);
if (!(spec_long
&& !type_sequence
[i
].long_flag
)
&& !(spec_long_long
&& !type_sequence
[i
].long_long_flag
)
&& !(spec_unsigned
&& !type_sequence
[i
].unsigned_flag
)
/* A hex or octal constant traditionally is unsigned. */
&& !(base
!= 10 && !flag_traditional
&& !type_sequence
[i
].unsigned_flag
)
/* A decimal constant can't be unsigned int
unless explicitly specified. */
&& !(base
== 10 && !spec_unsigned
&& *type_sequence
[i
].node_var
== unsigned_type_node
))
if (int_fits_type_p (yylval
.ttype
, *type_sequence
[i
].node_var
))
other_type
= *type_sequence
[i
].node_var
;
if (!flag_traditional
&& type
== long_unsigned_type_node
type
= long_integer_type_node
;
if (other_type
!= 0 && other_type
!= type
)
warning ("type of integer constant would be different without -traditional");
warning ("type of integer constant would be different with -traditional");
if (!spec_long
&& !spec_unsigned
&& !(flag_traditional
&& base
!= 10)
&& int_fits_type_p (yylval
.ttype
, integer_type_node
))
if (warn_traditional
&& base
!= 10)
warning ("small nondecimal constant becomes signed in ANSI C++");
type
= integer_type_node
;
else if (!spec_long
&& (base
!= 10 || spec_unsigned
)
&& int_fits_type_p (yylval
.ttype
, unsigned_type_node
))
/* Nondecimal constants try unsigned even in traditional C. */
type
= unsigned_type_node
;
else if (!spec_unsigned
&& !spec_long_long
&& int_fits_type_p (yylval
.ttype
, long_integer_type_node
))
type
= long_integer_type_node
;
else if (! spec_long_long
&& int_fits_type_p (yylval
.ttype
,
long_unsigned_type_node
))
if (warn_traditional
&& !spec_unsigned
)
warning ("large integer constant becomes unsigned in ANSI C++");
if (flag_traditional
&& !spec_unsigned
)
type
= long_integer_type_node
;
type
= long_unsigned_type_node
;
&& int_fits_type_p (yylval
.ttype
,
long_long_integer_type_node
))
type
= long_long_integer_type_node
;
else if (int_fits_type_p (yylval
.ttype
,
long_long_unsigned_type_node
))
if (warn_traditional
&& !spec_unsigned
)
warning ("large nondecimal constant is unsigned in ANSI C++");
if (flag_traditional
&& !spec_unsigned
)
type
= long_long_integer_type_node
;
type
= long_long_unsigned_type_node
;
type
= long_long_integer_type_node
;
warning ("integer constant out of range");
TREE_TYPE (yylval
.ttype
) = type
;
register int num_chars
= 0;
unsigned width
= TYPE_PRECISION (char_type_node
);
max_chars
= TYPE_PRECISION (integer_type_node
) / width
;
if (c
== '\'' || c
== EOF
)
c
= readescape (&ignore
);
if (width
< HOST_BITS_PER_INT
&& (unsigned) c
>= (1 << width
))
pedwarn ("escape sequence out of range for character");
pedwarn ("ANSI C++ forbids newline in character constant");
if (num_chars
> maxtoken
- 4)
extend_token_buffer (token_buffer
);
token_buffer
[num_chars
] = c
;
/* Merge character into result; ignore excess chars. */
if (num_chars
< max_chars
+ 1)
if (width
< HOST_BITS_PER_INT
)
result
= (result
<< width
) | (c
& ((1 << width
) - 1));
token_buffer
[num_chars
+ 1] = '\'';
token_buffer
[num_chars
+ 2] = 0;
error ("malformatted character constant");
error ("empty character constant");
else if (num_chars
> max_chars
)
error ("character constant too long");
else if (num_chars
!= 1 && ! flag_traditional
)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
int num_bits
= num_chars
* width
;
if (TREE_UNSIGNED (char_type_node
)
|| ((result
>> (num_bits
- 1)) & 1) == 0)
= build_int_2 (result
& ((unsigned HOST_WIDE_INT
) ~0
>> (HOST_BITS_PER_INT
- num_bits
)),
= build_int_2 (result
| ~((unsigned HOST_WIDE_INT
) ~0
>> (HOST_BITS_PER_INT
- num_bits
)),
TREE_TYPE (yylval
.ttype
) = char_type_node
;
TREE_TYPE (yylval
.ttype
) = integer_type_node
;
/* Set the initial shift state and convert the next sequence. */
/* In all locales L'\0' is zero and mbtowc will return zero,
|| (num_chars
== 1 && token_buffer
[1] != '\0'))
(void) mbtowc (NULL
, NULL
, 0);
if (mbtowc (& wc
, token_buffer
+ 1, num_chars
) == num_chars
)
warning ("Ignoring invalid multibyte character");
yylval
.ttype
= build_int_2 (result
, 0);
TREE_TYPE (yylval
.ttype
) = wchar_type_node
;
while (c
!= '"' && c
>= 0)
/* ignore_escape_flag is set for reading the filename in #line. */
if (!ignore_escape_flag
&& c
== '\\')
c
= readescape (&ignore
);
&& TYPE_PRECISION (char_type_node
) < HOST_BITS_PER_INT
&& c
>= ((unsigned) 1 << TYPE_PRECISION (char_type_node
)))
pedwarn ("escape sequence out of range for character");
pedwarn ("ANSI C++ forbids newline in string constant");
if (p
== token_buffer
+ maxtoken
)
p
= extend_token_buffer (p
);
error("Unterminated string");
/* We have read the entire constant.
Construct a STRING_CST for the result. */
/* If this is a L"..." wide-string, convert the multibyte string
to a wide character string. */
char *widep
= (char *) alloca ((p
- token_buffer
) * WCHAR_BYTES
);
len
= mbstowcs ((wchar_t *) widep
, token_buffer
+ 1, p
- token_buffer
);
if ((unsigned) len
>= (p
- token_buffer
))
warning ("Ignoring invalid multibyte string");
bzero (widep
+ (len
* WCHAR_BYTES
), WCHAR_BYTES
);
union { long l
; char c
[sizeof (long)]; } u
;
/* Determine whether host is little or big endian. */
big_endian
= u
.c
[sizeof (long) - 1];
wp
= widep
+ (big_endian
? WCHAR_BYTES
- 1 : 0);
bzero (widep
, (p
- token_buffer
) * WCHAR_BYTES
);
for (cp
= token_buffer
+ 1; cp
< p
; cp
++)
*wp
= *cp
, wp
+= WCHAR_BYTES
;
len
= p
- token_buffer
- 1;
yylval
.ttype
= build_string ((len
+ 1) * WCHAR_BYTES
, widep
);
TREE_TYPE (yylval
.ttype
) = wchar_array_type_node
;
yylval
.ttype
= build_string (p
- token_buffer
, token_buffer
+ 1);
TREE_TYPE (yylval
.ttype
) = char_array_type_node
;
yylval
.code
= PLUS_EXPR
; break;
yylval
.code
= MINUS_EXPR
; break;
yylval
.code
= BIT_AND_EXPR
; break;
yylval
.code
= BIT_IOR_EXPR
; break;
yylval
.code
= MULT_EXPR
; break;
yylval
.code
= TRUNC_DIV_EXPR
; break;
yylval
.code
= TRUNC_MOD_EXPR
; break;
yylval
.code
= BIT_XOR_EXPR
; break;
yylval
.code
= LSHIFT_EXPR
; break;
yylval
.code
= RSHIFT_EXPR
; break;
yylval
.code
= LT_EXPR
; break;
yylval
.code
= GT_EXPR
; break;
token_buffer
[1] = c1
= getch ();
value
= ARITHCOMPARE
; yylval
.code
= LE_EXPR
; goto done
;
value
= ARITHCOMPARE
; yylval
.code
= GE_EXPR
; goto done
;
value
= EQCOMPARE
; yylval
.code
= NE_EXPR
; goto done
;
value
= EQCOMPARE
; yylval
.code
= EQ_EXPR
; goto done
;
value
= ASSIGN
; goto done
;
value
= PLUSPLUS
; goto done
;
value
= MINUSMINUS
; goto done
;
value
= ANDAND
; goto done
;
else if ((c
== '-') && (c1
== '>'))
nextchar
= skip_white_space (getch ());
int next_c
= skip_white_space (getch ());
value
= POINTSAT_LEFT_RIGHT
;
else if (c1
== '?' && (c
== '<' || c
== '>'))
yylval
.code
= (c
== '<' ? MIN_EXPR
: MAX_EXPR
);
/* <?= or >?= expression. */
error ("use of `operator %s' is not standard C++",
/* Don't make yyparse think this is eof. */
/* try, weakly, to handle casts to pointers to functions. */
nextchar
= skip_white_space (getch ());
int next_c
= skip_white_space (getch ());
yylval
.ttype
= build1 (INDIRECT_REF
, 0, 0);
value
= PAREN_STAR_PAREN
;
else if (nextchar
== ')')
yylval
.ttype
= NULL_TREE
;
/* yylloc.last_line = lineno; */
d_kind
, t_kind
, s_kind
, r_kind
, e_kind
, c_kind
,
id_kind
, op_id_kind
, perm_list_kind
, temp_list_kind
,
vec_kind
, x_kind
, lang_decl
, lang_type
, all_kinds
extern int tree_node_counts
[];
extern int tree_node_sizes
[];
extern char *tree_node_kind_names
[];
/* Place to save freed lang_decls which were allocated on the
permanent_obstack. @@ Not currently used. */
tree free_lang_decl_chain
;
build_lang_decl (code
, name
, type
)
register tree t
= build_decl (code
, name
, type
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl
) / sizeof (int);
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
/* Could be that saveable is permanent and current is not. */
obstack
= &permanent_obstack
;
if (free_lang_decl_chain
&& obstack
== &permanent_obstack
)
pi
= (int *)free_lang_decl_chain
;
free_lang_decl_chain
= TREE_CHAIN (free_lang_decl_chain
);
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl
));
DECL_LANG_SPECIFIC (t
) = (struct lang_decl
*) pi
;
LANG_DECL_PERMANENT ((struct lang_decl
*) pi
)
= obstack
== &permanent_obstack
;
my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl
*) pi
)
== TREE_PERMANENT (t
), 234);
DECL_MAIN_VARIANT (t
) = t
;
if (current_lang_name
== lang_name_cplusplus
)
DECL_LANGUAGE (t
) = lang_cplusplus
;
if (code
== FUNCTION_DECL
&& name
!= 0
&& ! (IDENTIFIER_LENGTH (name
) == 4
&& IDENTIFIER_POINTER (name
)[0] == 'm'
&& strcmp (IDENTIFIER_POINTER (name
), "main") == 0)
&& ! (IDENTIFIER_LENGTH (name
) > 10
&& IDENTIFIER_POINTER (name
)[0] == '_'
&& IDENTIFIER_POINTER (name
)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (name
)+2, "builtin_", 8) == 0))
TREE_OVERLOADED (name
) = 1;
else if (current_lang_name
== lang_name_c
)
DECL_LANGUAGE (t
) = lang_c
;
else my_friendly_abort (64);
#if 0 /* not yet, should get fixed properly later */
id
= get_identifier (build_overload_name (type
, 1, 1));
DECL_ASSEMBLER_NAME (t
) = id
;
tree_node_counts
[(int)lang_decl
] += 1;
tree_node_sizes
[(int)lang_decl
] += sizeof(struct lang_decl
);
build_lang_field_decl (code
, name
, type
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
register tree t
= build_decl (code
, name
, type
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl_flags
) / sizeof (int);
#if 0 /* not yet, should get fixed properly later */
id
= get_identifier (build_overload_name (type
, 1, 1));
DECL_ASSEMBLER_NAME (t
) = id
;
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
my_friendly_assert (obstack
== &permanent_obstack
, 235);
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl_flags
));
DECL_LANG_SPECIFIC (t
) = (struct lang_decl
*) pi
;
if (TREE_CODE (node
) == FIELD_DECL
)
size
= sizeof (struct lang_decl_flags
);
size
= sizeof (struct lang_decl
);
pi
= (int *)obstack_alloc (&permanent_obstack
, size
);
bcopy ((char *)DECL_LANG_SPECIFIC (node
), (char *)pi
, size
);
DECL_LANG_SPECIFIC (node
) = (struct lang_decl
*)pi
;
extern struct obstack
*current_obstack
, *saveable_obstack
;
register tree t
= make_node (code
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_type
) / sizeof (int);
/* Set up some flags that give proper default behavior. */
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
my_friendly_assert (obstack
== &permanent_obstack
, 236);
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_type
));
TYPE_LANG_SPECIFIC (t
) = (struct lang_type
*) pi
;
CLASSTYPE_AS_LIST (t
) = build_tree_list (NULL_TREE
, t
);
CLASSTYPE_INTERFACE_UNKNOWN (t
) = interface_unknown
;
CLASSTYPE_INTERFACE_ONLY (t
) = interface_only
;
CLASSTYPE_VBASE_SIZE (t
) = integer_zero_node
;
TYPE_BINFO (t
) = make_binfo (integer_zero_node
, t
, 0, 0, 0);
CLASSTYPE_BINFO_AS_LIST (t
) = build_tree_list (NULL_TREE
, TYPE_BINFO (t
));
/* Make sure this is laid out, for ease of use later.
In the presence of parse errors, the normal was of assuring
this might not ever get executed, so we lay it out *immediately*. */
tree_node_counts
[(int)lang_type
] += 1;
tree_node_sizes
[(int)lang_type
] += sizeof(struct lang_type
);
copy_decl_lang_specific (decl
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
register int *old
= (int *)DECL_LANG_SPECIFIC (decl
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl
) / sizeof (int);
if (! TREE_PERMANENT (decl
))
obstack
= saveable_obstack
;
my_friendly_assert (obstack
== &permanent_obstack
, 237);
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl
));
DECL_LANG_SPECIFIC (decl
) = (struct lang_decl
*) pi
;
tree_node_counts
[(int)lang_decl
] += 1;
tree_node_sizes
[(int)lang_decl
] += sizeof(struct lang_decl
);
register tree prev
= 0, decl
, next
;
int this_time
= my_get_run_time ();
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
))
+= this_time
- body_time
;
fprintf (stderr
, "\n******\n");
print_time ("header files (total)", header_time
);
print_time ("main file (total)", this_time
- body_time
);
fprintf (stderr
, "ratio = %g : 1\n",
(double)header_time
/ (double)(this_time
- body_time
));
fprintf (stderr
, "\n******\n");
for (decl
= filename_times
; decl
; decl
= next
)
next
= IDENTIFIER_GLOBAL_VALUE (decl
);
IDENTIFIER_GLOBAL_VALUE (decl
) = prev
;
for (decl
= prev
; decl
; decl
= IDENTIFIER_GLOBAL_VALUE (decl
))
print_time (IDENTIFIER_POINTER (decl
),
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl
)));
compiler_error (s
, v
, v2
)
int v
, v2
; /* @@also used as pointer */
error_with_file_and_line (input_filename
, lineno
, "%s (compiler error)", buf
);
compiler_error_with_decl (decl
, s
)
report_error_function (0);
if (TREE_CODE (decl
) == PARM_DECL
)
fprintf (stderr
, "%s:%d: ",
DECL_SOURCE_FILE (DECL_CONTEXT (decl
)),
DECL_SOURCE_LINE (DECL_CONTEXT (decl
)));
fprintf (stderr
, "%s:%d: ",
DECL_SOURCE_FILE (decl
), DECL_SOURCE_LINE (decl
));
name
= lang_printable_name (decl
);
fprintf (stderr
, s
, name
);
fprintf (stderr
, s
, "((anonymous))");
fprintf (stderr
, " (compiler error)\n");
extern int input_redirected ();
/* We can't print string and character constants well
because the token_buffer contains the result of processing escapes. */
strcat (buf
, input_redirected ()
? " at end of saved text"
else if (token_buffer
[0] == 0)
strcat (buf
, " at null character");
else if (token_buffer
[0] == '"')
strcat (buf
, " before string constant");
else if (token_buffer
[0] == '\'')
strcat (buf
, " before character constant");
else if (token_buffer
[0] < 040 || (unsigned char) token_buffer
[0] >= 0177)
sprintf (buf
+ strlen (buf
), " before character 0%o",
(unsigned char) token_buffer
[0]);
strcat (buf
, " before `%s'");
error (buf
, token_buffer
);