|
|
1.1 root 1: /* Separate lexical analyzer for GNU C++.
2: Copyright (C) 1987, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
3: Hacked by Michael Tiemann ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
22: /* This file is the lexical analyzer for GNU C++. */
23:
24: /* Cause the `yydebug' variable to be defined. */
25: #define YYDEBUG 1
26:
27: #include <sys/types.h>
28: #include <stdio.h>
29: #include <errno.h>
30: #include <setjmp.h>
31: #include "config.h"
32: #include "input.h"
33: #include "tree.h"
34: #include "lex.h"
35: #include "parse.h"
36: #include "cp-tree.h"
37: #include "flags.h"
38: #include "obstack.h"
39:
40: #ifdef MULTIBYTE_CHARS
41: #include <stdlib.h>
42: #include <locale.h>
43: #endif
44:
45: #ifndef errno
46: extern int errno; /* needed for VAX. */
47: #endif
48: extern jmp_buf toplevel;
49:
50: #define obstack_chunk_alloc xmalloc
51: #define obstack_chunk_free free
52:
53: extern struct obstack *expression_obstack, permanent_obstack;
54: extern struct obstack *current_obstack, *saveable_obstack;
55:
56: extern double atof ();
57:
58: extern char *get_directive_line (); /* In c-common.c */
59:
60: /* Given a file name X, return the nondirectory portion.
61: Keep in mind that X can be computed more than once. */
62: #ifndef FILE_NAME_NONDIRECTORY
63: #define FILE_NAME_NONDIRECTORY(X) \
64: (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X)
65: #endif
66:
67: extern char *index ();
68: extern char *rindex ();
69:
70: void extract_interface_info ();
71: void yyerror ();
72:
73: /* This obstack is needed to hold text. It is not safe to use
74: TOKEN_BUFFER because `check_newline' calls `yylex'. */
75: struct obstack inline_text_obstack;
76: static char *inline_text_firstobj;
77:
78: /* This obstack is used to hold information about methods to be
79: synthesized. It should go away when synthesized methods are handled
80: properly (i.e. only when needed). */
81: struct obstack synth_obstack;
82: static char *synth_firstobj;
83:
84: int end_of_file;
85:
86: /* Pending language change.
87: Positive is push count, negative is pop count. */
88: int pending_lang_change = 0;
89:
90: /* Wrap the current header file in extern "C". */
91: static int c_header_level = 0;
92:
93: extern int first_token;
94: extern struct obstack token_obstack;
95:
96: /* ??? Don't really know where this goes yet. */
97: #if 1
98: #include "input.c"
99: #else
100: extern void put_back (/* int */);
101: extern int input_redirected ();
102: extern void feed_input (/* char *, int, struct obstack * */);
103: #endif
104:
105: /* Holds translations from TREE_CODEs to operator name strings,
106: i.e., opname_tab[PLUS_EXPR] == "+". */
107: char **opname_tab;
108: char **assignop_tab;
109:
110: extern int yychar; /* the lookahead symbol */
111: extern YYSTYPE yylval; /* the semantic value of the */
112: /* lookahead symbol */
113:
114: #if 0
115: YYLTYPE yylloc; /* location data for the lookahead */
116: /* symbol */
117: #endif
118:
119:
120: /* the declaration found for the last IDENTIFIER token read in.
121: yylex must look this up to detect typedefs, which get token type TYPENAME,
122: so it is left around in case the identifier is not a typedef but is
123: used in a context which makes it a reference to a variable. */
124: tree lastiddecl;
125:
126: /* The elements of `ridpointers' are identifier nodes
127: for the reserved type names and storage classes.
128: It is indexed by a RID_... value. */
129: tree ridpointers[(int) RID_MAX];
130:
131: /* We may keep statistics about how long which files took to compile. */
132: static int header_time, body_time;
133: static tree get_time_identifier ();
134: static tree filename_times;
135: static tree this_filename_time;
136:
137: /* For implementing #pragma unit. */
138: tree current_unit_name;
139: tree current_unit_language;
140:
141: /* Array for holding counts of the numbers of tokens seen. */
142: extern int *token_count;
143:
144: /* Textual definition used for default functions. */
145: static void default_copy_constructor_body ();
146: static void default_assign_ref_body ();
147:
148: /* Return something to represent absolute declarators containing a *.
149: TARGET is the absolute declarator that the * contains.
150: TYPE_QUALS is a list of modifiers such as const or volatile
151: to apply to the pointer type, represented as identifiers.
152:
153: We return an INDIRECT_REF whose "contents" are TARGET
154: and whose type is the modifier list. */
155:
156: tree
157: make_pointer_declarator (type_quals, target)
158: tree type_quals, target;
159: {
160: if (target && TREE_CODE (target) == IDENTIFIER_NODE
161: && ANON_AGGRNAME_P (target))
162: error ("type name expected before `*'");
163: target = build_parse_node (INDIRECT_REF, target);
164: TREE_TYPE (target) = type_quals;
165: return target;
166: }
167:
168: /* Return something to represent absolute declarators containing a &.
169: TARGET is the absolute declarator that the & contains.
170: TYPE_QUALS is a list of modifiers such as const or volatile
171: to apply to the reference type, represented as identifiers.
172:
173: We return an ADDR_EXPR whose "contents" are TARGET
174: and whose type is the modifier list. */
175:
176: tree
177: make_reference_declarator (type_quals, target)
178: tree type_quals, target;
179: {
180: if (target)
181: {
182: if (TREE_CODE (target) == ADDR_EXPR)
183: {
184: error ("cannot declare references to references");
185: return target;
186: }
187: if (TREE_CODE (target) == INDIRECT_REF)
188: {
189: error ("cannot declare pointers to references");
190: return target;
191: }
192: if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
193: error ("type name expected before `&'");
194: }
195: target = build_parse_node (ADDR_EXPR, target);
196: TREE_TYPE (target) = type_quals;
197: return target;
198: }
199:
200: /* Build names and nodes for overloaded operators. */
201:
202: tree ansi_opname[LAST_CPLUS_TREE_CODE];
203: tree ansi_assopname[LAST_CPLUS_TREE_CODE];
204:
205: char *
206: operator_name_string (name)
207: tree name;
208: {
209: char *opname = IDENTIFIER_POINTER (name) + 2;
210: tree *opname_table;
211: int i, assign;
212:
213: /* Works for builtin and user defined types. */
214: if (IDENTIFIER_GLOBAL_VALUE (name)
215: && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
216: return IDENTIFIER_POINTER (name);
217:
218: if (opname[0] == 'a' && opname[2] != '\0' && opname[2] != '_')
219: {
220: opname += 1;
221: assign = 1;
222: opname_table = ansi_assopname;
223: }
224: else
225: {
226: assign = 0;
227: opname_table = ansi_opname;
228: }
229:
230: for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
231: {
232: if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign]
233: && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign])
234: break;
235: }
236:
237: if (i == LAST_CPLUS_TREE_CODE)
238: return "<invalid operator>";
239:
240: if (assign)
241: return assignop_tab[i];
242: else
243: return opname_tab[i];
244: }
245:
246: int interface_only; /* whether or not current file is only for
247: interface definitions. */
248: int interface_unknown; /* whether or not we know this class
249: to behave according to #pragma interface. */
250:
251: /* lexical analyzer */
252:
253: /* File used for outputting assembler code. */
254: extern FILE *asm_out_file;
255:
256: #ifndef WCHAR_TYPE_SIZE
257: #ifdef INT_TYPE_SIZE
258: #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
259: #else
260: #define WCHAR_TYPE_SIZE BITS_PER_WORD
261: #endif
262: #endif
263:
264: /* Number of bytes in a wide character. */
265: #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
266:
267: static int maxtoken; /* Current nominal length of token buffer. */
268: char *token_buffer; /* Pointer to token buffer.
269: Actual allocated length is maxtoken + 2. */
270:
271: #include "hash.h"
272:
273: int check_newline ();
274:
275: /* Nonzero tells yylex to ignore \ in string constants. */
276: static int ignore_escape_flag = 0;
277:
278: static int skip_white_space ();
279:
280: static tree
281: get_time_identifier (name)
282: char *name;
283: {
284: tree time_identifier;
285: int len = strlen (name);
286: char *buf = (char *) alloca (len + 6);
287: strcpy (buf, "file ");
288: bcopy (name, buf+5, len);
289: buf[len+5] = '\0';
290: time_identifier = get_identifier (buf);
291: if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
292: {
293: push_obstacks_nochange ();
294: end_temporary_allocation ();
295: IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
296: IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
297: IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
298: filename_times = time_identifier;
299: pop_obstacks ();
300: }
301: return time_identifier;
302: }
303:
304: #ifdef __GNUC__
305: __inline
306: #endif
307: static int
308: my_get_run_time ()
309: {
310: int old_quiet_flag = quiet_flag;
311: int this_time;
312: quiet_flag = 0;
313: this_time = get_run_time ();
314: quiet_flag = old_quiet_flag;
315: return this_time;
316: }
317:
318: /* Table indexed by tree code giving a string containing a character
319: classifying the tree code. Possibilities are
320: t, d, s, c, r, <, 1 and 2. See cp/tree.def for details. */
321:
322: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
323:
324: char *cplus_tree_code_type[] = {
325: "x",
326: #include "tree.def"
327: };
328: #undef DEFTREECODE
329:
330: /* Table indexed by tree code giving number of expression
331: operands beyond the fixed part of the node structure.
332: Not used for types or decls. */
333:
334: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
335:
336: int cplus_tree_code_length[] = {
337: 0,
338: #include "tree.def"
339: };
340: #undef DEFTREECODE
341:
342: /* Names of tree components.
343: Used for printing out the tree and error messages. */
344: #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
345:
346: char *cplus_tree_code_name[] = {
347: "@@dummy",
348: #include "tree.def"
349: };
350: #undef DEFTREECODE
351:
352: /* toplev.c needs to call these. */
353:
354: void
355: lang_init ()
356: {
357: /* the beginning of the file is a new line; check for # */
358: /* With luck, we discover the real source file's name from that
359: and put it in input_filename. */
360: put_back (check_newline ());
361:
362: if (flag_cadillac)
363: cadillac_start ();
364: if (flag_gnu_xref) GNU_xref_begin (input_filename);
365: }
366:
367: void
368: lang_finish ()
369: {
370: extern int errorcount, sorrycount;
371: if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
372: }
373:
374: char *
375: lang_identify ()
376: {
377: return "cplusplus";
378: }
379:
380: void
381: init_filename_times ()
382: {
383: this_filename_time = get_time_identifier ("<top level>");
384: if (flag_detailed_statistics)
385: {
386: header_time = 0;
387: body_time = my_get_run_time ();
388: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
389: }
390: }
391:
392: /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
393: Stuck this hack in to get the files open correctly; this is called
394: in place of init_lex if we are an unexec'd binary. */
395: void
396: reinit_lang_specific ()
397: {
398: init_filename_times ();
399: reinit_search_statistics ();
400: }
401:
402: void
403: init_lex ()
404: {
405: extern char *(*decl_printable_name) ();
406:
407: int i;
408:
409: /* Initialize the lookahead machinery. */
410: init_spew ();
411:
412: /* Make identifier nodes long enough for the language-specific slots. */
413: set_identifier_size (sizeof (struct lang_identifier));
414: decl_printable_name = lang_printable_name;
415:
416: init_cplus_expand ();
417:
418: tree_code_type
419: = (char **) realloc (tree_code_type,
420: sizeof (char *) * LAST_CPLUS_TREE_CODE);
421: tree_code_length
422: = (int *) realloc (tree_code_length,
423: sizeof (int) * LAST_CPLUS_TREE_CODE);
424: tree_code_name
425: = (char **) realloc (tree_code_name,
426: sizeof (char *) * LAST_CPLUS_TREE_CODE);
427: bcopy ((char *)cplus_tree_code_type,
428: (char *)(tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE),
429: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
430: bcopy ((char *)cplus_tree_code_length,
431: (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
432: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
433: bcopy ((char *)cplus_tree_code_name,
434: (char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE),
435: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
436:
437: opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
438: bzero ((char *)opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
439: assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
440: bzero ((char *)assignop_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
441:
442: ansi_opname[0] = get_identifier ("<invalid operator>");
443: for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
444: {
445: ansi_opname[i] = ansi_opname[0];
446: ansi_assopname[i] = ansi_opname[0];
447: }
448:
449: ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml");
450: IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1;
451: ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR];
452: ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml");
453: IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1;
454: ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR];
455: ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md");
456: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1;
457: ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd");
458: IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1;
459: ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
460: ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
461: ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
462: ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi");
463: IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1;
464: ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR];
465: ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami");
466: IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1;
467: ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR];
468: ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs");
469: IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1;
470: ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars");
471: IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1;
472: ansi_opname[(int) NE_EXPR] = get_identifier ("__ne");
473: IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1;
474: ansi_opname[(int) GT_EXPR] = get_identifier ("__gt");
475: IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1;
476: ansi_opname[(int) GE_EXPR] = get_identifier ("__ge");
477: IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1;
478: ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or");
479: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1;
480: ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor");
481: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1;
482: ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa");
483: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1;
484: ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt");
485: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1;
486: ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp");
487: IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1;
488: ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR];
489: ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as");
490: IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1;
491: ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR];
492: ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm");
493: IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1;
494: ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv");
495: IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1;
496: ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv");
497: IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1;
498: ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
499: ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
500: ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
501: ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
502: ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
503: ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
504: ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
505: ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
506: ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
507: IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
508: ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
509: IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1;
510: ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR];
511: ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR];
512: ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls");
513: IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1;
514: ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als");
515: IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1;
516: ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq");
517: IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1;
518: ansi_opname[(int) LT_EXPR] = get_identifier ("__lt");
519: IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1;
520: ansi_opname[(int) LE_EXPR] = get_identifier ("__le");
521: IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1;
522: ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad");
523: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1;
524: ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad");
525: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1;
526: ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR];
527: ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR];
528: ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er");
529: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1;
530: ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer");
531: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1;
532: ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo");
533: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1;
534: ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co");
535: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1;
536: ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm");
537: IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1;
538: ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR];
539: ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf");
540: IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1;
541: ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm");
542: IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1;
543: ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl");
544: IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1;
545: ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc");
546: IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1;
547: ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw");
548: IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
549: ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
550: IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
551: ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn");
552: IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
553: ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
554: IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
555: ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
556: IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
557:
558: /* This is not true: these operators are not defined in ANSI,
559: but we need them anyway. */
560: ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn");
561: IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1;
562: ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx");
563: IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
564: ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
565: IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
566: ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
567: IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
568:
569: init_method ();
570: init_error ();
571: gcc_obstack_init (&inline_text_obstack);
572: inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
573: gcc_obstack_init (&synth_obstack);
574: synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
575:
576: /* Start it at 0, because check_newline is called at the very beginning
577: and will increment it to 1. */
578: lineno = 0;
579: input_filename = "<internal>";
580: current_function_decl = NULL;
581:
582: maxtoken = 40;
583: token_buffer = (char *) xmalloc (maxtoken + 2);
584:
585: ridpointers[(int) RID_INT] = get_identifier ("int");
586: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
587: build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
588: ridpointers[(int) RID_BOOL] = get_identifier ("bool");
589: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL],
590: build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL]));
591: ridpointers[(int) RID_CHAR] = get_identifier ("char");
592: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
593: build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
594: ridpointers[(int) RID_VOID] = get_identifier ("void");
595: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
596: build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
597: ridpointers[(int) RID_FLOAT] = get_identifier ("float");
598: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
599: build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
600: ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
601: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
602: build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
603: ridpointers[(int) RID_SHORT] = get_identifier ("short");
604: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
605: build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
606: ridpointers[(int) RID_LONG] = get_identifier ("long");
607: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
608: build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
609: ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
610: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
611: build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
612: ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
613: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
614: build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
615: ridpointers[(int) RID_INLINE] = get_identifier ("inline");
616: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
617: build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
618: ridpointers[(int) RID_CONST] = get_identifier ("const");
619: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
620: build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
621: ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
622: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
623: build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
624: ridpointers[(int) RID_AUTO] = get_identifier ("auto");
625: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
626: build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
627: ridpointers[(int) RID_STATIC] = get_identifier ("static");
628: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
629: build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
630: ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
631: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
632: build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
633: ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
634: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
635: build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
636: ridpointers[(int) RID_REGISTER] = get_identifier ("register");
637: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
638: build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
639:
640: /* C++ extensions. These are probably not correctly named. */
641: ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
642: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
643: build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
644: class_type_node = build_int_2 (class_type, 0);
645: TREE_TYPE (class_type_node) = class_type_node;
646: ridpointers[(int) RID_CLASS] = class_type_node;
647:
648: record_type_node = build_int_2 (record_type, 0);
649: TREE_TYPE (record_type_node) = record_type_node;
650: ridpointers[(int) RID_RECORD] = record_type_node;
651:
652: union_type_node = build_int_2 (union_type, 0);
653: TREE_TYPE (union_type_node) = union_type_node;
654: ridpointers[(int) RID_UNION] = union_type_node;
655:
656: enum_type_node = build_int_2 (enum_type, 0);
657: TREE_TYPE (enum_type_node) = enum_type_node;
658: ridpointers[(int) RID_ENUM] = enum_type_node;
659:
660: ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
661: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
662: build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
663: ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
664: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
665: build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
666:
667: ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
668: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
669: build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
670: ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
671: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
672: build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
673: ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
674: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
675: build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
676: ridpointers[(int) RID_TEMPLATE] = get_identifier ("template");
677: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE],
678: build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE]));
679: /* This is for ANSI C++. */
680: ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
681: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
682: build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
683:
684: /* Exception handling extensions. */
685: exception_type_node = build_int_2 (exception_type, 0);
686: TREE_TYPE (exception_type_node) = exception_type_node;
687: ridpointers[(int) RID_EXCEPTION] = exception_type_node;
688:
689: /* Signature handling extensions. */
690: signature_type_node = build_int_2 (signature_type, 0);
691: TREE_TYPE (signature_type_node) = signature_type_node;
692: ridpointers[(int) RID_SIGNATURE] = signature_type_node;
693:
694: opname_tab[(int) COMPONENT_REF] = "->";
695: opname_tab[(int) MEMBER_REF] = "->*";
696: opname_tab[(int) METHOD_CALL_EXPR] = "->()";
697: opname_tab[(int) INDIRECT_REF] = "(unary *)";
698: opname_tab[(int) ARRAY_REF] = "[]";
699: opname_tab[(int) MODIFY_EXPR] = "=";
700: opname_tab[(int) NEW_EXPR] = "new";
701: opname_tab[(int) DELETE_EXPR] = "delete";
702: opname_tab[(int) VEC_NEW_EXPR] = "new []";
703: opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
704: opname_tab[(int) COND_EXPR] = "... ? ... : ...";
705: opname_tab[(int) CALL_EXPR] = "()";
706: opname_tab[(int) PLUS_EXPR] = "+";
707: opname_tab[(int) MINUS_EXPR] = "-";
708: opname_tab[(int) MULT_EXPR] = "*";
709: opname_tab[(int) TRUNC_DIV_EXPR] = "/";
710: opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
711: opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
712: opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
713: opname_tab[(int) TRUNC_MOD_EXPR] = "%";
714: opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
715: opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
716: opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
717: opname_tab[(int) NEGATE_EXPR] = "-";
718: opname_tab[(int) MIN_EXPR] = "<?";
719: opname_tab[(int) MAX_EXPR] = ">?";
720: opname_tab[(int) ABS_EXPR] = "abs";
721: opname_tab[(int) FFS_EXPR] = "ffs";
722: opname_tab[(int) LSHIFT_EXPR] = "<<";
723: opname_tab[(int) RSHIFT_EXPR] = ">>";
724: opname_tab[(int) BIT_IOR_EXPR] = "|";
725: opname_tab[(int) BIT_XOR_EXPR] = "^";
726: opname_tab[(int) BIT_AND_EXPR] = "&";
727: opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
728: opname_tab[(int) BIT_NOT_EXPR] = "~";
729: opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
730: opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
731: opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
732: opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
733: opname_tab[(int) TRUTH_NOT_EXPR] = "!";
734: opname_tab[(int) LT_EXPR] = "<";
735: opname_tab[(int) LE_EXPR] = "<=";
736: opname_tab[(int) GT_EXPR] = ">";
737: opname_tab[(int) GE_EXPR] = ">=";
738: opname_tab[(int) EQ_EXPR] = "==";
739: opname_tab[(int) NE_EXPR] = "!=";
740: opname_tab[(int) IN_EXPR] = "in";
741: opname_tab[(int) RANGE_EXPR] = "..";
742: opname_tab[(int) CONVERT_EXPR] = "(unary +)";
743: opname_tab[(int) ADDR_EXPR] = "(unary &)";
744: opname_tab[(int) PREDECREMENT_EXPR] = "--";
745: opname_tab[(int) PREINCREMENT_EXPR] = "++";
746: opname_tab[(int) POSTDECREMENT_EXPR] = "--";
747: opname_tab[(int) POSTINCREMENT_EXPR] = "++";
748: opname_tab[(int) COMPOUND_EXPR] = ",";
749:
750: assignop_tab[(int) NOP_EXPR] = "=";
751: assignop_tab[(int) PLUS_EXPR] = "+=";
752: assignop_tab[(int) CONVERT_EXPR] = "+=";
753: assignop_tab[(int) MINUS_EXPR] = "-=";
754: assignop_tab[(int) NEGATE_EXPR] = "-=";
755: assignop_tab[(int) MULT_EXPR] = "*=";
756: assignop_tab[(int) INDIRECT_REF] = "*=";
757: assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
758: assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
759: assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
760: assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
761: assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
762: assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
763: assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
764: assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
765: assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
766: assignop_tab[(int) MIN_EXPR] = "<?=";
767: assignop_tab[(int) MAX_EXPR] = ">?=";
768: assignop_tab[(int) LSHIFT_EXPR] = "<<=";
769: assignop_tab[(int) RSHIFT_EXPR] = ">>=";
770: assignop_tab[(int) BIT_IOR_EXPR] = "|=";
771: assignop_tab[(int) BIT_XOR_EXPR] = "^=";
772: assignop_tab[(int) BIT_AND_EXPR] = "&=";
773: assignop_tab[(int) ADDR_EXPR] = "&=";
774:
775: init_filename_times ();
776:
777: /* Some options inhibit certain reserved words.
778: Clear those words out of the hash table so they won't be recognized. */
779: #define UNSET_RESERVED_WORD(STRING) \
780: do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \
781: if (s) s->name = ""; } while (0)
782:
783: #if 0
784: /* let's parse things, and if they use it, then give them an error. */
785: if (!flag_handle_exceptions)
786: {
787: UNSET_RESERVED_WORD ("throw");
788: UNSET_RESERVED_WORD ("try");
789: UNSET_RESERVED_WORD ("catch");
790: }
791: #endif
792:
793: if (! (flag_gc || flag_dossier))
794: {
795: UNSET_RESERVED_WORD ("classof");
796: UNSET_RESERVED_WORD ("headof");
797: }
798: if (! flag_handle_signatures)
799: {
800: /* Easiest way to not recognize signature
801: handling extensions... */
802: UNSET_RESERVED_WORD ("signature");
803: UNSET_RESERVED_WORD ("sigof");
804: }
805: if (flag_no_asm)
806: UNSET_RESERVED_WORD ("asm");
807: if (flag_no_asm || flag_traditional)
808: UNSET_RESERVED_WORD ("typeof");
809:
810: token_count = init_parse ();
811: interface_unknown = 1;
812: }
813:
814: void
815: reinit_parse_for_function ()
816: {
817: current_base_init_list = NULL_TREE;
818: current_member_init_list = NULL_TREE;
819: }
820:
821: #ifdef __GNUC__
822: __inline
823: #endif
824: void
825: yyprint (file, yychar, yylval)
826: FILE *file;
827: int yychar;
828: YYSTYPE yylval;
829: {
830: tree t;
831: switch (yychar)
832: {
833: case IDENTIFIER:
834: case TYPENAME:
835: case TYPESPEC:
836: case PTYPENAME:
837: case IDENTIFIER_DEFN:
838: case TYPENAME_DEFN:
839: case PTYPENAME_DEFN:
840: case TYPENAME_ELLIPSIS:
841: case SCSPEC:
842: case PRE_PARSED_CLASS_DECL:
843: t = yylval.ttype;
844: my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
845: if (IDENTIFIER_POINTER (t))
846: fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
847: break;
848: case AGGR:
849: if (yylval.ttype == class_type_node)
850: fprintf (file, " `class'");
851: else if (yylval.ttype == record_type_node)
852: fprintf (file, " `struct'");
853: else if (yylval.ttype == union_type_node)
854: fprintf (file, " `union'");
855: else if (yylval.ttype == enum_type_node)
856: fprintf (file, " `enum'");
857: else if (yylval.ttype == signature_type_node)
858: fprintf (file, " `signature'");
859: else
860: my_friendly_abort (80);
861: break;
862: }
863: }
864:
865: static int *reduce_count;
866: int *token_count;
867:
868: #define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
869: #define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
870:
871: int *
872: init_parse ()
873: {
874: #ifdef GATHER_STATISTICS
875: reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
876: bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
877: reduce_count += 1;
878: token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
879: bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
880: token_count += 1;
881: #endif
882: return token_count;
883: }
884:
885: #ifdef GATHER_STATISTICS
886: void
887: yyhook (yyn)
888: int yyn;
889: {
890: reduce_count[yyn] += 1;
891: }
892:
893: static int
894: reduce_cmp (p, q)
895: int *p, *q;
896: {
897: return reduce_count[*q] - reduce_count[*p];
898: }
899:
900: static int
901: token_cmp (p, q)
902: int *p, *q;
903: {
904: return token_count[*q] - token_count[*p];
905: }
906: #endif
907:
908: void
909: print_parse_statistics ()
910: {
911: #ifdef GATHER_STATISTICS
912: #if YYDEBUG != 0
913: int i;
914: int maxlen = REDUCE_LENGTH;
915: unsigned *sorted;
916:
917: if (reduce_count[-1] == 0)
918: return;
919:
920: if (TOKEN_LENGTH > REDUCE_LENGTH)
921: maxlen = TOKEN_LENGTH;
922: sorted = (unsigned *) alloca (sizeof (int) * maxlen);
923:
924: for (i = 0; i < TOKEN_LENGTH; i++)
925: sorted[i] = i;
926: qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
927: for (i = 0; i < TOKEN_LENGTH; i++)
928: {
929: int index = sorted[i];
930: if (token_count[index] == 0)
931: break;
932: if (token_count[index] < token_count[-1])
933: break;
934: fprintf (stderr, "token %d, `%s', count = %d\n",
935: index, yytname[YYTRANSLATE (index)], token_count[index]);
936: }
937: fprintf (stderr, "\n");
938: for (i = 0; i < REDUCE_LENGTH; i++)
939: sorted[i] = i;
940: qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
941: for (i = 0; i < REDUCE_LENGTH; i++)
942: {
943: int index = sorted[i];
944: if (reduce_count[index] == 0)
945: break;
946: if (reduce_count[index] < reduce_count[-1])
947: break;
948: fprintf (stderr, "rule %d, line %d, count = %d\n",
949: index, yyrline[index], reduce_count[index]);
950: }
951: fprintf (stderr, "\n");
952: #endif
953: #endif
954: }
955:
956: /* Sets the value of the 'yydebug' variable to VALUE.
957: This is a function so we don't have to have YYDEBUG defined
958: in order to build the compiler. */
959: void
960: set_yydebug (value)
961: int value;
962: {
963: #if YYDEBUG != 0
964: extern int yydebug;
965: yydebug = value;
966: #else
967: warning ("YYDEBUG not defined.");
968: #endif
969: }
970:
971:
972: /* Functions and data structures for #pragma interface.
973:
974: `#pragma implementation' means that the main file being compiled
975: is considered to implement (provide) the classes that appear in
976: its main body. I.e., if this is file "foo.cc", and class `bar'
977: is defined in "foo.cc", then we say that "foo.cc implements bar".
978:
979: All main input files "implement" themselves automagically.
980:
981: `#pragma interface' means that unless this file (of the form "foo.h"
982: is not presently being included by file "foo.cc", the
983: CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none
984: of the vtables nor any of the inline functions defined in foo.h
985: will ever be output.
986:
987: There are cases when we want to link files such as "defs.h" and
988: "main.cc". In this case, we give "defs.h" a `#pragma interface',
989: and "main.cc" has `#pragma implementation "defs.h"'. */
990:
991: struct impl_files
992: {
993: char *filename;
994: struct impl_files *next;
995: };
996:
997: static struct impl_files *impl_file_chain;
998:
999: /* Helper function to load global variables with interface
1000: information. */
1001: void
1002: extract_interface_info ()
1003: {
1004: tree fileinfo = 0;
1005:
1006: if (flag_alt_external_templates)
1007: {
1008: struct tinst_level *til = tinst_for_decl ();
1009:
1010: if (til)
1011: fileinfo = get_time_identifier (til->file);
1012: }
1013: if (!fileinfo)
1014: fileinfo = get_time_identifier (input_filename);
1015: fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
1016: interface_only = TREE_INT_CST_LOW (fileinfo);
1017: if (!processing_template_defn || flag_external_templates)
1018: interface_unknown = TREE_INT_CST_HIGH (fileinfo);
1019: }
1020:
1021: /* Return nonzero if S is not considered part of an
1022: INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
1023: static int
1024: interface_strcmp (s)
1025: char *s;
1026: {
1027: /* Set the interface/implementation bits for this scope. */
1028: struct impl_files *ifiles;
1029: char *s1;
1030:
1031: for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
1032: {
1033: char *t1 = ifiles->filename;
1034: s1 = s;
1035:
1036: if (*s1 != *t1 || *s1 == 0)
1037: continue;
1038:
1039: while (*s1 == *t1 && *s1 != 0)
1040: s1++, t1++;
1041:
1042: /* A match. */
1043: if (*s1 == *t1)
1044: return 0;
1045:
1046: /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */
1047: if (index (s1, '.') || index (t1, '.'))
1048: continue;
1049:
1050: if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
1051: continue;
1052:
1053: /* A match. */
1054: return 0;
1055: }
1056:
1057: /* No matches. */
1058: return 1;
1059: }
1060:
1061: void
1062: set_typedecl_interface_info (prev, vars)
1063: tree prev, vars;
1064: {
1065: tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
1066: tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
1067: tree type = TREE_TYPE (vars);
1068:
1069: CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
1070: = interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
1071: }
1072:
1073: void
1074: set_vardecl_interface_info (prev, vars)
1075: tree prev, vars;
1076: {
1077: tree type = DECL_CONTEXT (vars);
1078:
1079: if (CLASSTYPE_INTERFACE_KNOWN (type))
1080: {
1081: if (CLASSTYPE_INTERFACE_ONLY (type))
1082: set_typedecl_interface_info (prev, TYPE_NAME (type));
1083: else
1084: CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
1085: DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
1086: TREE_PUBLIC (vars) = 1;
1087: }
1088: }
1089:
1090: /* Called from the top level: if there are any pending inlines to
1091: do, set up to process them now. This function sets up the first function
1092: to be parsed; after it has been, the rule for fndef in parse.y will
1093: call process_next_inline to start working on the next one. */
1094: void
1095: do_pending_inlines ()
1096: {
1097: struct pending_inline *t;
1098:
1099: /* Oops, we're still dealing with the last batch. */
1100: if (yychar == PRE_PARSED_FUNCTION_DECL)
1101: return;
1102:
1103: /* Reverse the pending inline functions, since
1104: they were cons'd instead of appended. */
1105: {
1106: struct pending_inline *prev = 0, *tail, *bottom = 0;
1107: t = pending_inlines;
1108: pending_inlines = 0;
1109:
1110: for (; t; t = tail)
1111: {
1112: tail = t->next;
1113: t->next = prev;
1114: t->deja_vu = 1;
1115: prev = t;
1116: }
1117:
1118: /* This kludge should go away when synthesized methods are handled
1119: properly, i.e. only when needed. */
1120: for (t = prev; t; t = t->next)
1121: {
1122: if (t->lineno <= 0)
1123: {
1124: tree f = t->fndecl;
1125: DECL_PENDING_INLINE_INFO (f) = 0;
1126: interface_unknown = t->interface == 1;
1127: interface_only = t->interface == 0;
1128: switch (- t->lineno)
1129: {
1130: case 0: case 1:
1131: build_dtor (f); break;
1132: case 2:
1133: build_default_constructor (f); break;
1134: case 3: case 4:
1135: build_copy_constructor (f); break;
1136: case 5: case 6:
1137: build_assign_ref (f); break;
1138: default:
1139: ;
1140: }
1141: if (tail)
1142: tail->next = t->next;
1143: else
1144: prev = t->next;
1145: if (! bottom)
1146: bottom = t;
1147: }
1148: else
1149: tail = t;
1150: }
1151: if (bottom)
1152: {
1153: obstack_free (&synth_obstack, bottom);
1154: extract_interface_info ();
1155: }
1156: t = prev;
1157: }
1158:
1159: if (t == 0)
1160: return;
1161:
1162: /* Now start processing the first inline function. */
1163: my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
1164: 226);
1165: if (t->parm_vec)
1166: push_template_decls (t->parm_vec, t->bindings, 0);
1167: if (t->len > 0)
1168: {
1169: feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
1170: lineno = t->lineno;
1171: #if 0
1172: if (input_filename != t->filename)
1173: {
1174: input_filename = t->filename;
1175: /* Get interface/implementation back in sync. */
1176: extract_interface_info ();
1177: }
1178: #else
1179: input_filename = t->filename;
1180: interface_unknown = t->interface == 1;
1181: interface_only = t->interface == 0;
1182: #endif
1183: yychar = PRE_PARSED_FUNCTION_DECL;
1184: }
1185: /* Pass back a handle on the rest of the inline functions, so that they
1186: can be processed later. */
1187: yylval.ttype = build_tree_list ((tree) t, t->fndecl);
1188: #if 0
1189: if (flag_default_inline && t->fndecl
1190: /* If we're working from a template, don't change
1191: the `inline' state. */
1192: && t->parm_vec == NULL_TREE)
1193: DECL_INLINE (t->fndecl) = 1;
1194: #endif
1195: DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
1196: }
1197:
1198: extern struct pending_input *to_be_restored;
1199: static int nextchar = -1;
1200:
1201: /* Called from the fndecl rule in the parser when the function just parsed
1202: was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
1203: do_pending_inlines). */
1204: void
1205: process_next_inline (t)
1206: tree t;
1207: {
1208: struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
1209: my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
1210: 227);
1211: if (i->parm_vec)
1212: pop_template_decls (i->parm_vec, i->bindings, 0);
1213: i = i->next;
1214: if (yychar == YYEMPTY)
1215: yychar = yylex ();
1216: if (yychar != END_OF_SAVED_INPUT)
1217: {
1218: error ("parse error at end of saved function text");
1219: /* restore_pending_input will abort unless yychar is either
1220: * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
1221: * hosed, feed back YYEMPTY.
1222: * We also need to discard nextchar, since that may have gotten
1223: * set as well.
1224: */
1225: nextchar = -1;
1226: }
1227: yychar = YYEMPTY;
1228: if (to_be_restored == 0)
1229: my_friendly_abort (123);
1230: restore_pending_input (to_be_restored);
1231: to_be_restored = 0;
1232: if (i && i->fndecl != NULL_TREE)
1233: {
1234: my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
1235: 228);
1236: if (i->parm_vec)
1237: push_template_decls (i->parm_vec, i->bindings, 0);
1238: feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
1239: lineno = i->lineno;
1240: input_filename = i->filename;
1241: yychar = PRE_PARSED_FUNCTION_DECL;
1242: yylval.ttype = build_tree_list ((tree) i, i->fndecl);
1243: #if 0
1244: if (flag_default_inline
1245: /* If we're working from a template, don't change
1246: the `inline' state. */
1247: && i->parm_vec == NULL_TREE)
1248: DECL_INLINE (i->fndecl) = 1;
1249: #endif
1250: DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
1251: }
1252: if (i)
1253: {
1254: interface_unknown = i->interface == 1;
1255: interface_only = i->interface == 0;
1256: }
1257: else
1258: extract_interface_info ();
1259: }
1260:
1261: /* Since inline methods can refer to text which has not yet been seen,
1262: we store the text of the method in a structure which is placed in the
1263: DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
1264: After parsing the body of the class definition, the FUNCTION_DECL's are
1265: scanned to see which ones have this field set. Those are then digested
1266: one at a time.
1267:
1268: This function's FUNCTION_DECL will have a bit set in its common so
1269: that we know to watch out for it. */
1270:
1271: static void
1272: consume_string (this_obstack, matching_char)
1273: register struct obstack *this_obstack;
1274: int matching_char;
1275: {
1276: register int c;
1277: int starting_lineno = lineno;
1278: do
1279: {
1280: c = getch ();
1281: if (c == EOF)
1282: {
1283: int save_lineno = lineno;
1284: lineno = starting_lineno;
1285: if (matching_char == '"')
1286: error ("end of file encountered inside string constant");
1287: else
1288: error ("end of file encountered inside character constant");
1289: lineno = save_lineno;
1290: return;
1291: }
1292: if (c == '\\')
1293: {
1294: obstack_1grow (this_obstack, c);
1295: c = getch ();
1296: obstack_1grow (this_obstack, c);
1297:
1298: /* Make sure we continue the loop */
1299: c = 0;
1300: continue;
1301: }
1302: if (c == '\n')
1303: {
1304: if (pedantic)
1305: pedwarn ("ANSI C++ forbids newline in string constant");
1306: lineno++;
1307: }
1308: obstack_1grow (this_obstack, c);
1309: }
1310: while (c != matching_char);
1311: }
1312:
1313: static int nextyychar = YYEMPTY;
1314: static YYSTYPE nextyylval;
1315:
1316: struct pending_input {
1317: int nextchar, yychar, nextyychar, eof;
1318: YYSTYPE yylval, nextyylval;
1319: struct obstack token_obstack;
1320: int first_token;
1321: };
1322:
1323: struct pending_input *
1324: save_pending_input ()
1325: {
1326: struct pending_input *p;
1327: p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
1328: p->nextchar = nextchar;
1329: p->yychar = yychar;
1330: p->nextyychar = nextyychar;
1331: p->yylval = yylval;
1332: p->nextyylval = nextyylval;
1333: p->eof = end_of_file;
1334: yychar = nextyychar = YYEMPTY;
1335: nextchar = -1;
1336: p->first_token = first_token;
1337: p->token_obstack = token_obstack;
1338:
1339: first_token = 0;
1340: gcc_obstack_init (&token_obstack);
1341: end_of_file = 0;
1342: return p;
1343: }
1344:
1345: void
1346: restore_pending_input (p)
1347: struct pending_input *p;
1348: {
1349: my_friendly_assert (nextchar == -1, 229);
1350: nextchar = p->nextchar;
1351: my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
1352: yychar = p->yychar;
1353: my_friendly_assert (nextyychar == YYEMPTY, 231);
1354: nextyychar = p->nextyychar;
1355: yylval = p->yylval;
1356: nextyylval = p->nextyylval;
1357: first_token = p->first_token;
1358: obstack_free (&token_obstack, (char *) 0);
1359: token_obstack = p->token_obstack;
1360: end_of_file = p->eof;
1361: free (p);
1362: }
1363:
1364: /* Return next non-whitespace input character, which may come
1365: from `finput', or from `nextchar'. */
1366: static int
1367: yynextch ()
1368: {
1369: int c;
1370:
1371: if (nextchar >= 0)
1372: {
1373: c = nextchar;
1374: nextchar = -1;
1375: }
1376: else c = getch ();
1377: return skip_white_space (c);
1378: }
1379:
1380: /* Unget character CH from the input stream.
1381: If RESCAN is non-zero, then we want to `see' this
1382: character as the next input token. */
1383: void
1384: yyungetc (ch, rescan)
1385: int ch;
1386: int rescan;
1387: {
1388: /* Unget a character from the input stream. */
1389: if (yychar == YYEMPTY || rescan == 0)
1390: {
1391: if (nextchar >= 0)
1392: put_back (nextchar);
1393: nextchar = ch;
1394: }
1395: else
1396: {
1397: my_friendly_assert (nextyychar == YYEMPTY, 232);
1398: nextyychar = yychar;
1399: nextyylval = yylval;
1400: yychar = ch;
1401: }
1402: }
1403:
1404: /* This function stores away the text for an inline function that should
1405: be processed later. It decides how much later, and may need to move
1406: the info between obstacks; therefore, the caller should not refer to
1407: the T parameter after calling this function.
1408:
1409: This function also stores the list of template-parameter bindings that
1410: will be needed for expanding the template, if any. */
1411:
1412: static void
1413: store_pending_inline (decl, t)
1414: tree decl;
1415: struct pending_inline *t;
1416: {
1417: extern int processing_template_defn;
1418: int delay_to_eof = 0;
1419: struct pending_inline **inlines;
1420:
1421: t->fndecl = decl;
1422: /* Default: compile right away, and no extra bindings are needed. */
1423: t->parm_vec = t->bindings = 0;
1424: if (processing_template_defn)
1425: {
1426: tree type = current_class_type;
1427: /* Assumption: In this (possibly) nested class sequence, only
1428: one name will have template parms. */
1429: while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
1430: {
1431: tree decl = TYPE_NAME (type);
1432: tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
1433: if (tmpl)
1434: {
1435: t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
1436: t->bindings = TREE_VALUE (tmpl);
1437: }
1438: type = DECL_CONTEXT (decl);
1439: }
1440: if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
1441: || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
1442: {
1443: if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
1444: my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
1445: 233);
1446:
1447: /* Inline functions can be compiled immediately. Other functions
1448: will be output separately, so if we're in interface-only mode,
1449: punt them now, or output them now if we're doing implementations
1450: and we know no overrides will exist. Otherwise, we delay until
1451: end-of-file, to see if the definition is really required. */
1452: if (DECL_INLINE (decl))
1453: /* delay_to_eof == 0 */;
1454: else if (current_class_type && !interface_unknown)
1455: {
1456: if (interface_only)
1457: {
1458: #if 0
1459: print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
1460: #endif
1461: if (t->can_free)
1462: obstack_free (&inline_text_obstack, t->buf);
1463: DECL_PENDING_INLINE_INFO (decl) = 0;
1464: return;
1465: }
1466: }
1467: /* Don't delay the processing of virtual functions. */
1468: else if (DECL_VINDEX (decl) == NULL_TREE)
1469: delay_to_eof = 1;
1470: }
1471: else
1472: my_friendly_abort (58);
1473: }
1474:
1475: if (delay_to_eof)
1476: {
1477: extern struct pending_inline *pending_template_expansions;
1478:
1479: if (t->can_free)
1480: {
1481: char *free_to = t->buf;
1482: t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
1483: t->len + 1);
1484: t = (struct pending_inline *) obstack_copy (&permanent_obstack,
1485: (char *)t, sizeof (*t));
1486: obstack_free (&inline_text_obstack, free_to);
1487: }
1488: inlines = &pending_template_expansions;
1489: t->can_free = 0;
1490: }
1491: else
1492: {
1493: inlines = &pending_inlines;
1494: DECL_PENDING_INLINE_INFO (decl) = t;
1495: }
1496:
1497: /* Because we use obstacks, we must process these in precise order. */
1498: t->next = *inlines;
1499: *inlines = t;
1500: }
1501:
1502: void reinit_parse_for_block ();
1503:
1504: void
1505: reinit_parse_for_method (yychar, decl)
1506: int yychar;
1507: tree decl;
1508: {
1509: int len;
1510: int starting_lineno = lineno;
1511: char *starting_filename = input_filename;
1512:
1513: reinit_parse_for_block (yychar, &inline_text_obstack, 0);
1514:
1515: len = obstack_object_size (&inline_text_obstack);
1516: current_base_init_list = NULL_TREE;
1517: current_member_init_list = NULL_TREE;
1518: if (decl == void_type_node
1519: || (current_class_type && TYPE_REDEFINED (current_class_type)))
1520: {
1521: /* Happens when we get two declarations of the same
1522: function in the same scope. */
1523: char *buf = obstack_finish (&inline_text_obstack);
1524: obstack_free (&inline_text_obstack, buf);
1525: return;
1526: }
1527: else
1528: {
1529: struct pending_inline *t;
1530: char *buf = obstack_finish (&inline_text_obstack);
1531:
1532: t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
1533: sizeof (struct pending_inline));
1534: t->lineno = starting_lineno;
1535: t->filename = starting_filename;
1536: t->token = YYEMPTY;
1537: t->token_value = 0;
1538: t->buf = buf;
1539: t->len = len;
1540: t->can_free = 1;
1541: t->deja_vu = 0;
1542: if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
1543: warn_if_unknown_interface ();
1544: t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
1545: store_pending_inline (decl, t);
1546: }
1547: }
1548:
1549: /* Consume a block -- actually, a method or template definition beginning
1550: with `:' or `{' -- and save it away on the specified obstack.
1551:
1552: Argument IS_TEMPLATE indicates which set of error messages should be
1553: output if something goes wrong. This should really be cleaned up somehow,
1554: without loss of clarity. */
1555: void
1556: reinit_parse_for_block (yychar, obstackp, is_template)
1557: int yychar;
1558: struct obstack *obstackp;
1559: int is_template;
1560: {
1561: register int c = 0;
1562: int blev = 1;
1563: int starting_lineno = lineno;
1564: char *starting_filename = input_filename;
1565: int len;
1566: int look_for_semicolon = 0;
1567: int look_for_lbrac = 0;
1568:
1569: if (yychar == '{')
1570: obstack_1grow (obstackp, '{');
1571: else if (yychar == '=')
1572: look_for_semicolon = 1;
1573: else if (yychar != ':' && (yychar != RETURN || is_template))
1574: {
1575: yyerror (is_template
1576: ? "parse error in template specification"
1577: : "parse error in method specification");
1578: obstack_1grow (obstackp, '{');
1579: }
1580: else
1581: {
1582: obstack_1grow (obstackp, yychar);
1583: look_for_lbrac = 1;
1584: blev = 0;
1585: }
1586:
1587: if (nextchar != EOF)
1588: {
1589: c = nextchar;
1590: nextchar = EOF;
1591: }
1592: else
1593: c = getch ();
1594:
1595: while (c != EOF)
1596: {
1597: int this_lineno = lineno;
1598:
1599: c = skip_white_space (c);
1600:
1601: /* Don't lose our cool if there are lots of comments. */
1602: if (lineno == this_lineno + 1)
1603: obstack_1grow (obstackp, '\n');
1604: else if (lineno == this_lineno)
1605: ;
1606: else if (lineno - this_lineno < 10)
1607: {
1608: int i;
1609: for (i = lineno - this_lineno; i > 0; i--)
1610: obstack_1grow (obstackp, '\n');
1611: }
1612: else
1613: {
1614: char buf[16];
1615: sprintf (buf, "\n# %d \"", lineno);
1616: len = strlen (buf);
1617: obstack_grow (obstackp, buf, len);
1618:
1619: len = strlen (input_filename);
1620: obstack_grow (obstackp, input_filename, len);
1621: obstack_1grow (obstackp, '\"');
1622: obstack_1grow (obstackp, '\n');
1623: }
1624:
1625: while (c > ' ') /* ASCII dependent... */
1626: {
1627: obstack_1grow (obstackp, c);
1628: if (c == '{')
1629: {
1630: look_for_lbrac = 0;
1631: blev++;
1632: }
1633: else if (c == '}')
1634: {
1635: blev--;
1636: if (blev == 0 && !look_for_semicolon)
1637: goto done;
1638: }
1639: else if (c == '\\')
1640: {
1641: /* Don't act on the next character...e.g, doing an escaped
1642: double-quote. */
1643: c = getch ();
1644: if (c == EOF)
1645: {
1646: error_with_file_and_line (starting_filename,
1647: starting_lineno,
1648: "end of file read inside definition");
1649: goto done;
1650: }
1651: obstack_1grow (obstackp, c);
1652: }
1653: else if (c == '\"')
1654: consume_string (obstackp, c);
1655: else if (c == '\'')
1656: consume_string (obstackp, c);
1657: else if (c == ';')
1658: {
1659: if (look_for_lbrac)
1660: {
1661: error (is_template
1662: ? "template body missing"
1663: : "function body for constructor missing");
1664: obstack_1grow (obstackp, '{');
1665: obstack_1grow (obstackp, '}');
1666: len += 2;
1667: goto done;
1668: }
1669: else if (look_for_semicolon && blev == 0)
1670: goto done;
1671: }
1672: c = getch ();
1673: }
1674:
1675: if (c == EOF)
1676: {
1677: error_with_file_and_line (starting_filename,
1678: starting_lineno,
1679: "end of file read inside definition");
1680: goto done;
1681: }
1682: else if (c != '\n')
1683: {
1684: obstack_1grow (obstackp, c);
1685: c = getch ();
1686: }
1687: }
1688: done:
1689: obstack_1grow (obstackp, '\0');
1690: }
1691:
1692: /* Build a default function named NAME for type TYPE.
1693: KIND says what to build.
1694:
1695: When KIND == 0, build default destructor.
1696: When KIND == 1, build virtual destructor.
1697: When KIND == 2, build default constructor.
1698: When KIND == 3, build default X(const X&) constructor.
1699: When KIND == 4, build default X(X&) constructor.
1700: When KIND == 5, build default operator = (const X&).
1701: When KIND == 6, build default operator = (X&). */
1702:
1703: tree
1704: cons_up_default_function (type, name, kind)
1705: tree type, name;
1706: int kind;
1707: {
1708: extern tree void_list_node;
1709: char *func_buf = NULL;
1710: int func_len = 0;
1711: tree declspecs = NULL_TREE;
1712: tree fn, args;
1713: tree argtype;
1714: int retref = 0;
1715:
1716: name = constructor_name (name);
1717: switch (kind)
1718: {
1719: /* Destructors. */
1720: case 1:
1721: declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
1722: /* Fall through... */
1723: case 0:
1724: name = build_parse_node (BIT_NOT_EXPR, name);
1725: /* Fall through... */
1726: case 2:
1727: /* Default constructor. */
1728: args = void_list_node;
1729: break;
1730:
1731: case 3:
1732: type = build_type_variant (type, 1, 0);
1733: /* Fall through... */
1734: case 4:
1735: /* According to ARM $12.8, the default copy ctor will be declared, but
1736: not defined, unless it's needed. */
1737: argtype = build_reference_type (type);
1738: args = tree_cons (NULL_TREE,
1739: build_tree_list (hash_tree_chain (argtype, NULL_TREE),
1740: get_identifier ("_ctor_arg")),
1741: void_list_node);
1742: break;
1743:
1744: case 5:
1745: type = build_type_variant (type, 1, 0);
1746: /* Fall through... */
1747: case 6:
1748: retref = 1;
1749: declspecs = build_decl_list (NULL_TREE, name);
1750:
1751: name = ansi_opname [(int) MODIFY_EXPR];
1752:
1753: argtype = build_reference_type (type);
1754: args = tree_cons (NULL_TREE,
1755: build_tree_list (hash_tree_chain (argtype, NULL_TREE),
1756: get_identifier ("_ctor_arg")),
1757: void_list_node);
1758: break;
1759:
1760: default:
1761: my_friendly_abort (59);
1762: }
1763:
1764: declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE],
1765: declspecs);
1766:
1767: TREE_PARMLIST (args) = 1;
1768:
1769: {
1770: tree declarator = build_parse_node (CALL_EXPR, name, args, NULL_TREE);
1771: if (retref)
1772: declarator = build_parse_node (ADDR_EXPR, declarator);
1773:
1774: fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
1775: }
1776:
1777: if (fn == void_type_node)
1778: return fn;
1779:
1780: if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
1781: SET_DECL_IMPLICIT_INSTANTIATION (fn);
1782:
1783: /* This kludge should go away when synthesized methods are handled
1784: properly, i.e. only when needed. */
1785: {
1786: struct pending_inline *t;
1787: t = (struct pending_inline *)
1788: obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
1789: t->lineno = -kind;
1790: t->can_free = 0;
1791: t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
1792: store_pending_inline (fn, t);
1793: }
1794:
1795: #ifdef DEBUG_DEFAULT_FUNCTIONS
1796: { char *fn_type = NULL;
1797: tree t = name;
1798: switch (kind)
1799: {
1800: case 0: fn_type = "default destructor"; break;
1801: case 1: fn_type = "virtual destructor"; break;
1802: case 2: fn_type = "default constructor"; break;
1803: case 3: fn_type = "default X(const X&)"; break;
1804: case 4: fn_type = "default X(X&)"; break;
1805: }
1806: if (fn_type)
1807: {
1808: if (TREE_CODE (name) == BIT_NOT_EXPR)
1809: t = TREE_OPERAND (name, 0);
1810: fprintf (stderr, "[[[[ %s for %s:\n%s]]]]\n", fn_type,
1811: IDENTIFIER_POINTER (t), func_buf);
1812: }
1813: }
1814: #endif /* DEBUG_DEFAULT_FUNCTIONS */
1815:
1816: /* Show that this function was generated by the compiler. */
1817: SET_DECL_ARTIFICIAL (fn);
1818:
1819: return fn;
1820: }
1821:
1822: #if 0
1823: /* Used by default_copy_constructor_body. For the anonymous union
1824: in TYPE, return the member that is at least as large as the rest
1825: of the members, so we can copy it. */
1826: static tree
1827: largest_union_member (type)
1828: tree type;
1829: {
1830: tree f, type_size = TYPE_SIZE (type);
1831:
1832: for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
1833: if (simple_cst_equal (DECL_SIZE (f), type_size))
1834: return f;
1835:
1836: /* We should always find one. */
1837: my_friendly_abort (323);
1838: return NULL_TREE;
1839: }
1840:
1841: /* Construct the body of a default assignment operator.
1842: Mostly copied directly from default_copy_constructor_body. */
1843: static void
1844: default_assign_ref_body (bufp, lenp, type, fields)
1845: char **bufp;
1846: int *lenp;
1847: tree type, fields;
1848: {
1849: static struct obstack body;
1850: static int inited = FALSE;
1851: int n_bases = CLASSTYPE_N_BASECLASSES (type);
1852: char *tbuf;
1853: int tgot, tneed;
1854:
1855: if (!inited)
1856: {
1857: obstack_init (&body);
1858: inited = TRUE;
1859: }
1860: body.next_free = body.object_base;
1861:
1862: obstack_1grow (&body, '{');
1863:
1864: /* Small buffer for sprintf(). */
1865:
1866: tgot = 100;
1867: tbuf = (char *) alloca (tgot);
1868:
1869: /* If we don't need a real op=, just do a bitwise copy. */
1870: if (! TYPE_HAS_COMPLEX_ASSIGN_REF (type))
1871: {
1872: tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));return *this;}";
1873: *lenp = strlen (tbuf);
1874: *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
1875: strcpy (*bufp, tbuf);
1876: return;
1877: }
1878:
1879: if (TREE_CODE (type) == UNION_TYPE)
1880: {
1881: if (fields)
1882: {
1883: tree main = fields;
1884: char * s;
1885: tree f;
1886:
1887: for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f))
1888: if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)),
1889: TYPE_SIZE (TREE_TYPE (f))))
1890: main = f;
1891:
1892: s = IDENTIFIER_POINTER (DECL_NAME (main));
1893:
1894: tneed = (2 * strlen (s)) + 28;
1895: if (tgot < tneed)
1896: {
1897: tgot = tneed;
1898: tbuf = (char *) alloca (tgot);
1899: }
1900:
1901: sprintf (tbuf, "{%s=_ctor_arg.%s;return *this;}", s, s);
1902: }
1903: else
1904: tbuf = "{}";
1905:
1906: *lenp = strlen (tbuf);
1907: *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
1908: strcpy (*bufp, tbuf);
1909: return;
1910: }
1911:
1912: /* Construct base classes...
1913: FIXME: Does not deal with multiple inheritance and virtual bases
1914: correctly. See g++.old-deja/g++.jason/opeq5.C for a testcase.
1915: We need to do wacky things if everything between us and the virtual
1916: base (by all paths) has a "complex" op=. */
1917:
1918: if (n_bases)
1919: {
1920: tree bases = TYPE_BINFO_BASETYPES (type);
1921: int i = 0;
1922:
1923: for (i = 0; i < n_bases; i++)
1924: {
1925: tree binfo = TREE_VEC_ELT (bases, i);
1926: tree btype, name;
1927: char *s;
1928:
1929: btype = BINFO_TYPE (binfo);
1930: name = TYPE_NESTED_NAME (btype);
1931: s = IDENTIFIER_POINTER (name);
1932:
1933: tneed = (2 * strlen (s)) + 42;
1934: if (tgot < tneed)
1935: {
1936: tgot = tneed;
1937: tbuf = (char *) alloca (tgot);
1938: }
1939:
1940: sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s,
1941: TYPE_READONLY (type) ? "const " : "",
1942: CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
1943: s);
1944: obstack_grow (&body, tbuf, strlen (tbuf));
1945: }
1946: }
1947:
1948: /* Construct fields. */
1949:
1950: if (fields)
1951: {
1952: tree f;
1953:
1954: for (f = fields; f; f = TREE_CHAIN (f))
1955: {
1956: if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
1957: {
1958: char *s;
1959: tree x;
1960: tree t = TREE_TYPE (f);
1961:
1962: if (DECL_NAME (f))
1963: x = f;
1964: else if (t != NULL_TREE
1965: && TREE_CODE (t) == UNION_TYPE
1966: && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
1967: && ANON_AGGRNAME_P (TYPE_NAME (t)))
1968: || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
1969: && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
1970: && TYPE_FIELDS (t) != NULL_TREE)
1971: x = largest_union_member (t);
1972: else
1973: continue;
1974:
1975: s = IDENTIFIER_POINTER (DECL_NAME (x));
1976: tneed = (2 * strlen (s)) + 13;
1977: if (tgot < tneed)
1978: {
1979: tgot = tneed;
1980: tbuf = (char *) alloca (tgot);
1981: }
1982:
1983: sprintf (tbuf, "%s=_ctor_arg.%s;", s, s);
1984: obstack_grow (&body, tbuf, strlen (tbuf));
1985: }
1986: }
1987: }
1988:
1989: obstack_grow (&body, "return *this;}", 15);
1990:
1991: *lenp = obstack_object_size (&body) - 1;
1992: *bufp = obstack_alloc (&inline_text_obstack, *lenp);
1993:
1994: strcpy (*bufp, body.object_base);
1995: }
1996:
1997: /* Construct the body of a default copy constructor. */
1998: static void
1999: default_copy_constructor_body (bufp, lenp, type, fields)
2000: char **bufp;
2001: int *lenp;
2002: tree type, fields;
2003: {
2004: static struct obstack prologue;
2005: static int inited = FALSE;
2006: int n_bases = CLASSTYPE_N_BASECLASSES (type);
2007: char sep = ':';
2008: char *tbuf;
2009: int tgot, tneed;
2010:
2011: /* Create a buffer to call base class constructors and construct members
2012: (fields). */
2013:
2014: if (!inited)
2015: {
2016: obstack_init (&prologue);
2017: inited = TRUE;
2018: }
2019: prologue.next_free = prologue.object_base;
2020:
2021: /* If we don't need a real copy ctor, just do a bitwise copy. */
2022: if (! TYPE_HAS_COMPLEX_INIT_REF (type))
2023: {
2024: tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));}";
2025: *lenp = strlen (tbuf);
2026: *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
2027: strcpy (*bufp, tbuf);
2028: return;
2029: }
2030:
2031: /* Small buffer for sprintf(). */
2032:
2033: tgot = 100;
2034: tbuf = (char *) alloca (tgot);
2035:
2036: if (TREE_CODE (type) == UNION_TYPE)
2037: {
2038: if (fields)
2039: {
2040: tree main = fields;
2041: char * s;
2042: tree f;
2043:
2044: for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f))
2045: if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)),
2046: TYPE_SIZE (TREE_TYPE (f))))
2047: main = f;
2048:
2049: s = IDENTIFIER_POINTER (DECL_NAME (main));
2050: tneed = (2 * strlen (s)) + 16;
2051: if (tgot < tneed)
2052: {
2053: tgot = tneed;
2054: tbuf = (char *) alloca (tgot);
2055: }
2056:
2057: sprintf (tbuf, ":%s(_ctor_arg.%s){}", s, s);
2058: }
2059: else
2060: tbuf = "{}";
2061:
2062: *lenp = strlen (tbuf);
2063: *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
2064: strcpy (*bufp, tbuf);
2065: return;
2066: }
2067:
2068: /* Construct base classes... */
2069:
2070: if (n_bases)
2071: {
2072: /* Note that CLASSTYPE_VBASECLASSES isn't set yet... */
2073: tree v = get_vbase_types (type);
2074: tree bases = TYPE_BINFO_BASETYPES (type);
2075: int i = 0;
2076:
2077: for (;;)
2078: {
2079: tree binfo, btype, name;
2080: char *s;
2081:
2082: if (v)
2083: {
2084: binfo = v;
2085: v = TREE_CHAIN (v);
2086: }
2087: else if (i < n_bases)
2088: {
2089: binfo = TREE_VEC_ELT (bases, i++);
2090: if (TREE_VIA_VIRTUAL (binfo))
2091: continue;
2092: }
2093: else
2094: break;
2095:
2096: btype = BINFO_TYPE (binfo);
2097: name = TYPE_NESTED_NAME (btype);
2098: s = IDENTIFIER_POINTER (name);
2099:
2100: tneed = (2 * strlen (s)) + 39;
2101: if (tgot < tneed)
2102: {
2103: tgot = tneed;
2104: tbuf = (char *) alloca (tgot);
2105: }
2106:
2107: sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s,
2108: TYPE_READONLY (type) ? "const " : "",
2109: CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
2110: s);
2111: sep = ',';
2112: obstack_grow (&prologue, tbuf, strlen (tbuf));
2113: }
2114: }
2115:
2116: /* Construct fields. */
2117:
2118: if (fields)
2119: {
2120: tree f;
2121:
2122: for (f = fields; f; f = TREE_CHAIN (f))
2123: {
2124: if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
2125: {
2126: char *s;
2127: tree x;
2128: tree t = TREE_TYPE (f);
2129:
2130: if (DECL_NAME (f))
2131: x = f;
2132: else if (t != NULL_TREE
2133: && TREE_CODE (t) == UNION_TYPE
2134: && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
2135: && ANON_AGGRNAME_P (TYPE_NAME (t)))
2136: || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
2137: && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
2138: && TYPE_FIELDS (t) != NULL_TREE)
2139: x = largest_union_member (t);
2140: else
2141: continue;
2142:
2143: s = IDENTIFIER_POINTER (DECL_NAME (x));
2144: tneed = (2 * strlen (s)) + 30;
2145: if (tgot < tneed)
2146: {
2147: tgot = tneed;
2148: tbuf = (char *) alloca (tgot);
2149: }
2150:
2151: sprintf (tbuf, "%c%s(_ctor_arg.%s)", sep, s, s);
2152: sep = ',';
2153: obstack_grow (&prologue, tbuf, strlen (tbuf));
2154: }
2155: }
2156: }
2157:
2158: /* Concatenate constructor body to prologue. */
2159:
2160: *lenp = obstack_object_size (&prologue) + 2;
2161: *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
2162:
2163: obstack_1grow (&prologue, '\0');
2164:
2165: strcpy (*bufp, prologue.object_base);
2166: strcat (*bufp, "{}");
2167: }
2168: #endif
2169:
2170: /* Heuristic to tell whether the user is missing a semicolon
2171: after a struct or enum declaration. Emit an error message
2172: if we know the user has blown it. */
2173: void
2174: check_for_missing_semicolon (type)
2175: tree type;
2176: {
2177: if (yychar < 0)
2178: yychar = yylex ();
2179:
2180: if ((yychar > 255
2181: && yychar != SCSPEC
2182: && yychar != IDENTIFIER
2183: && yychar != TYPENAME)
2184: || end_of_file)
2185: {
2186: if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
2187: error ("semicolon missing after %s declaration",
2188: TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
2189: else
2190: cp_error ("semicolon missing after declaration of `%T'", type);
2191: shadow_tag (build_tree_list (0, type));
2192: }
2193: /* Could probably also hack cases where class { ... } f (); appears. */
2194: clear_anon_tags ();
2195: }
2196:
2197: void
2198: note_got_semicolon (type)
2199: tree type;
2200: {
2201: if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
2202: my_friendly_abort (60);
2203: if (IS_AGGR_TYPE (type))
2204: CLASSTYPE_GOT_SEMICOLON (type) = 1;
2205: }
2206:
2207: void
2208: note_list_got_semicolon (declspecs)
2209: tree declspecs;
2210: {
2211: tree link;
2212:
2213: for (link = declspecs; link; link = TREE_CHAIN (link))
2214: {
2215: tree type = TREE_VALUE (link);
2216: if (TREE_CODE_CLASS (TREE_CODE (type)) == 't')
2217: note_got_semicolon (type);
2218: }
2219: clear_anon_tags ();
2220: }
2221:
2222: /* If C is not whitespace, return C.
2223: Otherwise skip whitespace and return first nonwhite char read. */
2224:
2225: static int
2226: skip_white_space (c)
2227: register int c;
2228: {
2229: for (;;)
2230: {
2231: switch (c)
2232: {
2233: case '\n':
2234: c = check_newline ();
2235: break;
2236:
2237: case ' ':
2238: case '\t':
2239: case '\f':
2240: case '\r':
2241: case '\v':
2242: case '\b':
2243: do
2244: c = getch ();
2245: while (c == ' ' || c == '\t');
2246: break;
2247:
2248: case '\\':
2249: c = getch ();
2250: if (c == '\n')
2251: lineno++;
2252: else
2253: error ("stray '\\' in program");
2254: c = getch ();
2255: break;
2256:
2257: default:
2258: return (c);
2259: }
2260: }
2261: }
2262:
2263:
2264:
2265: /* Make the token buffer longer, preserving the data in it.
2266: P should point to just beyond the last valid character in the old buffer.
2267: The value we return is a pointer to the new buffer
2268: at a place corresponding to P. */
2269:
2270: static char *
2271: extend_token_buffer (p)
2272: char *p;
2273: {
2274: int offset = p - token_buffer;
2275:
2276: maxtoken = maxtoken * 2 + 10;
2277: token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
2278:
2279: return token_buffer + offset;
2280: }
2281:
2282: static int
2283: get_last_nonwhite_on_line ()
2284: {
2285: register int c;
2286:
2287: /* Is this the last nonwhite stuff on the line? */
2288: if (nextchar >= 0)
2289: c = nextchar, nextchar = -1;
2290: else
2291: c = getch ();
2292:
2293: while (c == ' ' || c == '\t')
2294: c = getch ();
2295: return c;
2296: }
2297:
2298: /* At the beginning of a line, increment the line number
2299: and process any #-directive on this line.
2300: If the line is a #-directive, read the entire line and return a newline.
2301: Otherwise, return the line's first non-whitespace character. */
2302:
2303: int
2304: check_newline ()
2305: {
2306: register int c;
2307: register int token;
2308:
2309: /* Read first nonwhite char on the line. Do this before incrementing the
2310: line number, in case we're at the end of saved text. */
2311:
2312: do
2313: c = getch ();
2314: while (c == ' ' || c == '\t');
2315:
2316: lineno++;
2317:
2318: if (c != '#')
2319: {
2320: /* If not #, return it so caller will use it. */
2321: return c;
2322: }
2323:
2324: /* Read first nonwhite char after the `#'. */
2325:
2326: do
2327: c = getch ();
2328: while (c == ' ' || c == '\t');
2329:
2330: /* If a letter follows, then if the word here is `line', skip
2331: it and ignore it; otherwise, ignore the line, with an error
2332: if the word isn't `pragma'. */
2333:
2334: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
2335: {
2336: if (c == 'p')
2337: {
2338: if (getch () == 'r'
2339: && getch () == 'a'
2340: && getch () == 'g'
2341: && getch () == 'm'
2342: && getch () == 'a')
2343: {
2344: /* Read first nonwhite char after the `#pragma'. */
2345:
2346: do
2347: c = getch ();
2348: while (c == ' ' || c == '\t');
2349:
2350: if (c == 'v'
2351: && getch () == 't'
2352: && getch () == 'a'
2353: && getch () == 'b'
2354: && getch () == 'l'
2355: && getch () == 'e'
2356: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2357: {
2358: extern tree pending_vtables;
2359:
2360: /* More follows: it must be a string constant (class name). */
2361: token = real_yylex ();
2362: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
2363: {
2364: error ("invalid #pragma vtable");
2365: goto skipline;
2366: }
2367: if (write_virtuals != 2)
2368: {
2369: warning ("use `+e2' option to enable #pragma vtable");
2370: goto skipline;
2371: }
2372: pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
2373: if (nextchar < 0)
2374: nextchar = getch ();
2375: c = nextchar;
2376: if (c != '\n')
2377: warning ("trailing characters ignored");
2378: }
2379: else if (c == 'u'
2380: && getch () == 'n'
2381: && getch () == 'i'
2382: && getch () == 't'
2383: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2384: {
2385: /* More follows: it must be a string constant (unit name). */
2386: token = real_yylex ();
2387: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
2388: {
2389: error ("invalid #pragma unit");
2390: goto skipline;
2391: }
2392: current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
2393: current_unit_language = current_lang_name;
2394: if (nextchar < 0)
2395: nextchar = getch ();
2396: c = nextchar;
2397: if (c != '\n')
2398: warning ("trailing characters ignored");
2399: }
2400: else if (c == 'i')
2401: {
2402: tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
2403: c = getch ();
2404:
2405: if (c == 'n'
2406: && getch () == 't'
2407: && getch () == 'e'
2408: && getch () == 'r'
2409: && getch () == 'f'
2410: && getch () == 'a'
2411: && getch () == 'c'
2412: && getch () == 'e'
2413: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2414: {
2415: int warned_already = 0;
2416: char *main_filename = input_filename;
2417:
2418: main_filename = FILE_NAME_NONDIRECTORY (main_filename);
2419: while (c == ' ' || c == '\t')
2420: c = getch ();
2421: if (c != '\n')
2422: {
2423: put_back (c);
2424: token = real_yylex ();
2425: if (token != STRING
2426: || TREE_CODE (yylval.ttype) != STRING_CST)
2427: {
2428: error ("invalid `#pragma interface'");
2429: goto skipline;
2430: }
2431: main_filename = TREE_STRING_POINTER (yylval.ttype);
2432: c = getch();
2433: put_back (c);
2434: }
2435:
2436: while (c == ' ' || c == '\t')
2437: c = getch ();
2438:
2439: while (c != '\n')
2440: {
2441: if (!warned_already && extra_warnings
2442: && c != ' ' && c != '\t' && c != '\n')
2443: {
2444: warning ("garbage after `#pragma interface' ignored");
2445: warned_already = 1;
2446: }
2447: c = getch ();
2448: }
2449:
2450: write_virtuals = 3;
2451:
2452: if (impl_file_chain == 0)
2453: {
2454: /* If this is zero at this point, then we are
2455: auto-implementing. */
2456: if (main_input_filename == 0)
2457: main_input_filename = input_filename;
2458:
2459: #ifdef AUTO_IMPLEMENT
2460: filename = FILE_NAME_NONDIRECTORY (main_input_filename);
2461: fi = get_time_identifier (filename);
2462: fi = IDENTIFIER_CLASS_VALUE (fi);
2463: TREE_INT_CST_LOW (fi) = 0;
2464: TREE_INT_CST_HIGH (fi) = 1;
2465: /* Get default. */
2466: impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
2467: impl_file_chain->filename = filename;
2468: impl_file_chain->next = 0;
2469: #endif
2470: }
2471:
2472: interface_only = interface_strcmp (main_filename);
2473: interface_unknown = 0;
2474: TREE_INT_CST_LOW (fileinfo) = interface_only;
2475: TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
2476: }
2477: else if (c == 'm'
2478: && getch () == 'p'
2479: && getch () == 'l'
2480: && getch () == 'e'
2481: && getch () == 'm'
2482: && getch () == 'e'
2483: && getch () == 'n'
2484: && getch () == 't'
2485: && getch () == 'a'
2486: && getch () == 't'
2487: && getch () == 'i'
2488: && getch () == 'o'
2489: && getch () == 'n'
2490: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2491: {
2492: int warned_already = 0;
2493: char *main_filename = main_input_filename ? main_input_filename : input_filename;
2494:
2495: main_filename = FILE_NAME_NONDIRECTORY (main_filename);
2496: while (c == ' ' || c == '\t')
2497: c = getch ();
2498: if (c != '\n')
2499: {
2500: put_back (c);
2501: token = real_yylex ();
2502: if (token != STRING
2503: || TREE_CODE (yylval.ttype) != STRING_CST)
2504: {
2505: error ("invalid `#pragma implementation'");
2506: goto skipline;
2507: }
2508: main_filename = TREE_STRING_POINTER (yylval.ttype);
2509: c = getch();
2510: put_back (c);
2511: }
2512:
2513: while (c == ' ' || c == '\t')
2514: c = getch ();
2515:
2516: while (c != '\n')
2517: {
2518: if (!warned_already && extra_warnings
2519: && c != ' ' && c != '\t' && c != '\n')
2520: {
2521: warning ("garbage after `#pragma implementation' ignored");
2522: warned_already = 1;
2523: }
2524: c = getch ();
2525: }
2526:
2527: if (write_virtuals == 3)
2528: {
2529: struct impl_files *ifiles = impl_file_chain;
2530: while (ifiles)
2531: {
2532: if (! strcmp (ifiles->filename, main_filename))
2533: break;
2534: ifiles = ifiles->next;
2535: }
2536: if (ifiles == 0)
2537: {
2538: ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
2539: ifiles->filename = main_filename;
2540: ifiles->next = impl_file_chain;
2541: impl_file_chain = ifiles;
2542: }
2543: }
2544: else if ((main_input_filename != 0
2545: && ! strcmp (main_input_filename, input_filename))
2546: || ! strcmp (input_filename, main_filename))
2547: {
2548: write_virtuals = 3;
2549: if (impl_file_chain == 0)
2550: {
2551: impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
2552: impl_file_chain->filename = main_filename;
2553: impl_file_chain->next = 0;
2554: }
2555: }
2556: else
2557: error ("`#pragma implementation' can only appear at top-level");
2558: interface_only = 0;
2559: #if 1
2560: /* We make this non-zero so that we infer decl linkage
2561: in the impl file only for variables first declared
2562: in the interface file. */
2563: interface_unknown = 1;
2564: #else
2565: /* We make this zero so that templates in the impl
2566: file will be emitted properly. */
2567: interface_unknown = 0;
2568: #endif
2569: TREE_INT_CST_LOW (fileinfo) = interface_only;
2570: TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
2571: }
2572: }
2573: }
2574: goto skipline;
2575: }
2576: else if (c == 'd')
2577: {
2578: if (getch () == 'e'
2579: && getch () == 'f'
2580: && getch () == 'i'
2581: && getch () == 'n'
2582: && getch () == 'e'
2583: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2584: {
2585: #ifdef DWARF_DEBUGGING_INFO
2586: if ((debug_info_level == DINFO_LEVEL_VERBOSE)
2587: && (write_symbols == DWARF_DEBUG))
2588: dwarfout_define (lineno, get_directive_line (finput));
2589: #endif /* DWARF_DEBUGGING_INFO */
2590: goto skipline;
2591: }
2592: }
2593: else if (c == 'u')
2594: {
2595: if (getch () == 'n'
2596: && getch () == 'd'
2597: && getch () == 'e'
2598: && getch () == 'f'
2599: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
2600: {
2601: #ifdef DWARF_DEBUGGING_INFO
2602: if ((debug_info_level == DINFO_LEVEL_VERBOSE)
2603: && (write_symbols == DWARF_DEBUG))
2604: dwarfout_undef (lineno, get_directive_line (finput));
2605: #endif /* DWARF_DEBUGGING_INFO */
2606: goto skipline;
2607: }
2608: }
2609: else if (c == 'l')
2610: {
2611: if (getch () == 'i'
2612: && getch () == 'n'
2613: && getch () == 'e'
2614: && ((c = getch ()) == ' ' || c == '\t'))
2615: goto linenum;
2616: }
2617: else if (c == 'i')
2618: {
2619: if (getch () == 'd'
2620: && getch () == 'e'
2621: && getch () == 'n'
2622: && getch () == 't'
2623: && ((c = getch ()) == ' ' || c == '\t'))
2624: {
2625: #ifdef ASM_OUTPUT_IDENT
2626: extern FILE *asm_out_file;
2627: #endif
2628: /* #ident. The pedantic warning is now in cccp.c. */
2629:
2630: /* Here we have just seen `#ident '.
2631: A string constant should follow. */
2632:
2633: while (c == ' ' || c == '\t')
2634: c = getch ();
2635:
2636: /* If no argument, ignore the line. */
2637: if (c == '\n')
2638: return c;
2639:
2640: put_back (c);
2641: token = real_yylex ();
2642: if (token != STRING
2643: || TREE_CODE (yylval.ttype) != STRING_CST)
2644: {
2645: error ("invalid #ident");
2646: goto skipline;
2647: }
2648:
2649: if (! flag_no_ident)
2650: {
2651: #ifdef ASM_OUTPUT_IDENT
2652: ASM_OUTPUT_IDENT (asm_out_file,
2653: TREE_STRING_POINTER (yylval.ttype));
2654: #endif
2655: }
2656:
2657: /* Skip the rest of this line. */
2658: goto skipline;
2659: }
2660: }
2661: else if (c == 'n')
2662: {
2663: if (getch () == 'e'
2664: && getch () == 'w'
2665: && getch () == 'w'
2666: && getch () == 'o'
2667: && getch () == 'r'
2668: && getch () == 'l'
2669: && getch () == 'd'
2670: && ((c = getch ()) == ' ' || c == '\t'))
2671: {
2672: /* Used to test incremental compilation. */
2673: sorry ("#pragma newworld");
2674: goto skipline;
2675: }
2676: }
2677: error ("undefined or invalid # directive");
2678: goto skipline;
2679: }
2680:
2681: linenum:
2682: /* Here we have either `#line' or `# <nonletter>'.
2683: In either case, it should be a line number; a digit should follow. */
2684:
2685: while (c == ' ' || c == '\t')
2686: c = getch ();
2687:
2688: /* If the # is the only nonwhite char on the line,
2689: just ignore it. Check the new newline. */
2690: if (c == '\n')
2691: return c;
2692:
2693: /* Something follows the #; read a token. */
2694:
2695: put_back (c);
2696: token = real_yylex ();
2697:
2698: if (token == CONSTANT
2699: && TREE_CODE (yylval.ttype) == INTEGER_CST)
2700: {
2701: int old_lineno = lineno;
2702: enum { act_none, act_push, act_pop } action = act_none;
2703: int entering_system_header = 0;
2704: int entering_c_header = 0;
2705:
2706: /* subtract one, because it is the following line that
2707: gets the specified number */
2708:
2709: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
2710: c = get_last_nonwhite_on_line ();
2711: if (c == '\n')
2712: {
2713: /* No more: store the line number and check following line. */
2714: lineno = l;
2715: return c;
2716: }
2717: put_back (c);
2718:
2719: /* More follows: it must be a string constant (filename). */
2720:
2721: /* Read the string constant, but don't treat \ as special. */
2722: ignore_escape_flag = 1;
2723: token = real_yylex ();
2724: ignore_escape_flag = 0;
2725:
2726: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
2727: {
2728: error ("invalid #line");
2729: goto skipline;
2730: }
2731:
2732: /* Changing files again. This means currently collected time
2733: is charged against header time, and body time starts back
2734: at 0. */
2735: if (flag_detailed_statistics)
2736: {
2737: int this_time = my_get_run_time ();
2738: tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
2739: header_time += this_time - body_time;
2740: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
2741: += this_time - body_time;
2742: this_filename_time = time_identifier;
2743: body_time = this_time;
2744: }
2745:
2746: if (flag_cadillac)
2747: cadillac_note_source ();
2748:
2749: input_filename
2750: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
2751: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
2752: lineno = l;
2753: GNU_xref_file (input_filename);
2754:
2755: if (main_input_filename == 0)
2756: {
2757: struct impl_files *ifiles = impl_file_chain;
2758:
2759: if (ifiles)
2760: {
2761: while (ifiles->next)
2762: ifiles = ifiles->next;
2763: ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename);
2764: }
2765:
2766: main_input_filename = input_filename;
2767: if (write_virtuals == 3)
2768: walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
2769: }
2770:
2771: extract_interface_info ();
2772:
2773: c = get_last_nonwhite_on_line ();
2774: if (c != '\n')
2775: {
2776: put_back (c);
2777:
2778: token = real_yylex ();
2779:
2780: /* `1' after file name means entering new file.
2781: `2' after file name means just left a file. */
2782:
2783: if (token == CONSTANT
2784: && TREE_CODE (yylval.ttype) == INTEGER_CST)
2785: {
2786: if (TREE_INT_CST_LOW (yylval.ttype) == 1)
2787: action = act_push;
2788: else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
2789: action = act_pop;
2790:
2791: if (action)
2792: {
2793: c = get_last_nonwhite_on_line ();
2794: if (c != '\n')
2795: {
2796: put_back (c);
2797: token = real_yylex ();
2798: }
2799: }
2800: }
2801:
2802: /* `3' after file name means this is a system header file. */
2803:
2804: if (token == CONSTANT
2805: && TREE_CODE (yylval.ttype) == INTEGER_CST
2806: && TREE_INT_CST_LOW (yylval.ttype) == 3)
2807: {
2808: entering_system_header = 1;
2809:
2810: c = get_last_nonwhite_on_line ();
2811: if (c != '\n')
2812: {
2813: put_back (c);
2814: token = real_yylex ();
2815: }
2816: }
2817:
2818: /* `4' after file name means this is a C header file. */
2819:
2820: if (token == CONSTANT
2821: && TREE_CODE (yylval.ttype) == INTEGER_CST
2822: && TREE_INT_CST_LOW (yylval.ttype) == 4)
2823: {
2824: entering_c_header = 1;
2825:
2826: c = get_last_nonwhite_on_line ();
2827: if (c != '\n')
2828: {
2829: put_back (c);
2830: token = real_yylex ();
2831: }
2832: }
2833:
2834: /* Do the actions implied by the preceeding numbers. */
2835:
2836: if (action == act_push)
2837: {
2838: /* Pushing to a new file. */
2839: struct file_stack *p;
2840:
2841: p = (struct file_stack *) xmalloc (sizeof (struct file_stack));
2842: input_file_stack->line = old_lineno;
2843: p->next = input_file_stack;
2844: p->name = input_filename;
2845: input_file_stack = p;
2846: input_file_stack_tick++;
2847: #ifdef DWARF_DEBUGGING_INFO
2848: if (debug_info_level == DINFO_LEVEL_VERBOSE
2849: && write_symbols == DWARF_DEBUG)
2850: dwarfout_start_new_source_file (input_filename);
2851: #endif /* DWARF_DEBUGGING_INFO */
2852: if (flag_cadillac)
2853: cadillac_push_source ();
2854: in_system_header = entering_system_header;
2855: if (c_header_level)
2856: ++c_header_level;
2857: else if (entering_c_header)
2858: {
2859: c_header_level = 1;
2860: ++pending_lang_change;
2861: }
2862: }
2863: else if (action == act_pop)
2864: {
2865: /* Popping out of a file. */
2866: if (input_file_stack->next)
2867: {
2868: struct file_stack *p;
2869:
2870: if (c_header_level && --c_header_level == 0)
2871: {
2872: if (entering_c_header)
2873: warning ("badly nested C headers from preprocessor");
2874: --pending_lang_change;
2875: }
2876: if (flag_cadillac)
2877: cadillac_pop_source ();
2878: in_system_header = entering_system_header;
2879:
2880: p = input_file_stack;
2881: input_file_stack = p->next;
2882: free (p);
2883: input_file_stack_tick++;
2884: #ifdef DWARF_DEBUGGING_INFO
2885: if (debug_info_level == DINFO_LEVEL_VERBOSE
2886: && write_symbols == DWARF_DEBUG)
2887: dwarfout_resume_previous_source_file (input_file_stack->line);
2888: #endif /* DWARF_DEBUGGING_INFO */
2889: }
2890: else
2891: error ("#-lines for entering and leaving files don't match");
2892: }
2893: else
2894: {
2895: in_system_header = entering_system_header;
2896: if (flag_cadillac)
2897: cadillac_switch_source (-1);
2898: }
2899: }
2900:
2901: /* If NEXTCHAR is not end of line, we don't care what it is. */
2902: if (nextchar == '\n')
2903: return '\n';
2904: }
2905: else
2906: error ("invalid #-line");
2907:
2908: /* skip the rest of this line. */
2909: skipline:
2910: if (c == '\n')
2911: return c;
2912: while ((c = getch ()) != EOF && c != '\n');
2913: return c;
2914: }
2915:
2916: void
2917: do_pending_lang_change ()
2918: {
2919: for (; pending_lang_change > 0; --pending_lang_change)
2920: push_lang_context (lang_name_c);
2921: for (; pending_lang_change < 0; ++pending_lang_change)
2922: pop_lang_context ();
2923: }
2924:
2925: #if 0
2926: #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
2927: #define isdigit(char) (char >= '0' && char <= '9')
2928: #else
2929: #include <ctype.h>
2930: #endif
2931:
2932: #define ENDFILE -1 /* token that represents end-of-file */
2933:
2934: /* Read an escape sequence, returning its equivalent as a character,
2935: or store 1 in *ignore_ptr if it is backslash-newline. */
2936:
2937: static int
2938: readescape (ignore_ptr)
2939: int *ignore_ptr;
2940: {
2941: register int c = getch ();
2942: register int code;
2943: register unsigned count;
2944: unsigned firstdig;
2945: int nonnull;
2946:
2947: switch (c)
2948: {
2949: case 'x':
2950: if (warn_traditional)
2951: warning ("the meaning of `\\x' varies with -traditional");
2952:
2953: if (flag_traditional)
2954: return c;
2955:
2956: code = 0;
2957: count = 0;
2958: nonnull = 0;
2959: while (1)
2960: {
2961: c = getch ();
2962: if (! isxdigit (c))
2963: {
2964: put_back (c);
2965: break;
2966: }
2967: code *= 16;
2968: if (c >= 'a' && c <= 'f')
2969: code += c - 'a' + 10;
2970: if (c >= 'A' && c <= 'F')
2971: code += c - 'A' + 10;
2972: if (c >= '0' && c <= '9')
2973: code += c - '0';
2974: if (code != 0 || count != 0)
2975: {
2976: if (count == 0)
2977: firstdig = code;
2978: count++;
2979: }
2980: nonnull = 1;
2981: }
2982: if (! nonnull)
2983: error ("\\x used with no following hex digits");
2984: else if (count == 0)
2985: /* Digits are all 0's. Ok. */
2986: ;
2987: else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
2988: || (count > 1
2989: && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
2990: <= firstdig)))
2991: pedwarn ("hex escape out of range");
2992: return code;
2993:
2994: case '0': case '1': case '2': case '3': case '4':
2995: case '5': case '6': case '7':
2996: code = 0;
2997: count = 0;
2998: while ((c <= '7') && (c >= '0') && (count++ < 3))
2999: {
3000: code = (code * 8) + (c - '0');
3001: c = getch ();
3002: }
3003: put_back (c);
3004: return code;
3005:
3006: case '\\': case '\'': case '"':
3007: return c;
3008:
3009: case '\n':
3010: lineno++;
3011: *ignore_ptr = 1;
3012: return 0;
3013:
3014: case 'n':
3015: return TARGET_NEWLINE;
3016:
3017: case 't':
3018: return TARGET_TAB;
3019:
3020: case 'r':
3021: return TARGET_CR;
3022:
3023: case 'f':
3024: return TARGET_FF;
3025:
3026: case 'b':
3027: return TARGET_BS;
3028:
3029: case 'a':
3030: if (warn_traditional)
3031: warning ("the meaning of `\\a' varies with -traditional");
3032:
3033: if (flag_traditional)
3034: return c;
3035: return TARGET_BELL;
3036:
3037: case 'v':
3038: return TARGET_VT;
3039:
3040: case 'e':
3041: case 'E':
3042: if (pedantic)
3043: pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
3044: return 033;
3045:
3046: case '?':
3047: return c;
3048:
3049: /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
3050: case '(':
3051: case '{':
3052: case '[':
3053: /* `\%' is used to prevent SCCS from getting confused. */
3054: case '%':
3055: if (pedantic)
3056: pedwarn ("unknown escape sequence `\\%c'", c);
3057: return c;
3058: }
3059: if (c >= 040 && c < 0177)
3060: pedwarn ("unknown escape sequence `\\%c'", c);
3061: else
3062: pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
3063: return c;
3064: }
3065:
3066: /* Value is 1 (or 2) if we should try to make the next identifier look like
3067: a typename (when it may be a local variable or a class variable).
3068: Value is 0 if we treat this name in a default fashion. */
3069: int looking_for_typename = 0;
3070:
3071: #if 0
3072: /* NO LONGER USED: Value is -1 if we must not see a type name. */
3073: void
3074: dont_see_typename ()
3075: {
3076: looking_for_typename = -1;
3077: if (yychar == TYPENAME || yychar == PTYPENAME)
3078: {
3079: yychar = IDENTIFIER;
3080: lastiddecl = 0;
3081: }
3082: }
3083: #endif
3084:
3085: #ifdef __GNUC__
3086: extern __inline int identifier_type ();
3087: __inline
3088: #endif
3089: int
3090: identifier_type (decl)
3091: tree decl;
3092: {
3093: if (TREE_CODE (decl) == TEMPLATE_DECL
3094: && DECL_TEMPLATE_IS_CLASS (decl))
3095: return PTYPENAME;
3096: if (TREE_CODE (decl) != TYPE_DECL)
3097: return IDENTIFIER;
3098: return TYPENAME;
3099: }
3100:
3101: void
3102: see_typename ()
3103: {
3104: looking_for_typename = 0;
3105: if (yychar == IDENTIFIER)
3106: {
3107: lastiddecl = lookup_name (yylval.ttype, -2);
3108: if (lastiddecl == 0)
3109: {
3110: if (flag_labels_ok)
3111: lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
3112: }
3113: else
3114: yychar = identifier_type (lastiddecl);
3115: }
3116: }
3117:
3118: tree
3119: do_identifier (token)
3120: register tree token;
3121: {
3122: register tree id = lastiddecl;
3123:
3124: if (yychar == YYEMPTY)
3125: yychar = yylex ();
3126: /* Scope class declarations before global
3127: declarations. */
3128: if (id == IDENTIFIER_GLOBAL_VALUE (token)
3129: && current_class_type != 0
3130: && TYPE_SIZE (current_class_type) == 0
3131: && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
3132: {
3133: /* Could be from one of the base classes. */
3134: tree field = lookup_field (current_class_type, token, 1, 0);
3135: if (field == 0)
3136: ;
3137: else if (field == error_mark_node)
3138: /* We have already generated the error message.
3139: But we still want to return this value. */
3140: id = lookup_field (current_class_type, token, 0, 0);
3141: else if (TREE_CODE (field) == VAR_DECL
3142: || TREE_CODE (field) == CONST_DECL)
3143: id = field;
3144: else if (TREE_CODE (field) != FIELD_DECL)
3145: my_friendly_abort (61);
3146: else
3147: {
3148: cp_error ("invalid use of member `%D' from base class `%T'", field,
3149: DECL_FIELD_CONTEXT (field));
3150: id = error_mark_node;
3151: return id;
3152: }
3153: }
3154:
3155: /* Remember that this name has been used in the class definition, as per
3156: [class.scope0] */
3157: if (id && current_class_type
3158: && TYPE_BEING_DEFINED (current_class_type)
3159: && ! IDENTIFIER_CLASS_VALUE (token))
3160: pushdecl_class_level (id);
3161:
3162: if (!id || id == error_mark_node)
3163: {
3164: if (id == error_mark_node && current_class_type != NULL_TREE)
3165: {
3166: id = lookup_nested_field (token, 1);
3167: /* In lookup_nested_field(), we marked this so we can gracefully
3168: leave this whole mess. */
3169: if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
3170: return id;
3171: }
3172: if (yychar == '(' || yychar == LEFT_RIGHT)
3173: {
3174: id = implicitly_declare (token);
3175: }
3176: else if (current_function_decl == 0)
3177: {
3178: cp_error ("`%D' was not declared in this scope", token);
3179: id = error_mark_node;
3180: }
3181: else
3182: {
3183: if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
3184: || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
3185: {
3186: static int undeclared_variable_notice;
3187:
3188: cp_error ("`%D' undeclared (first use this function)", token);
3189:
3190: if (! undeclared_variable_notice)
3191: {
3192: error ("(Each undeclared identifier is reported only once");
3193: error ("for each function it appears in.)");
3194: undeclared_variable_notice = 1;
3195: }
3196: }
3197: id = error_mark_node;
3198: /* Prevent repeated error messages. */
3199: IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
3200: SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
3201: }
3202: }
3203: /* TREE_USED is set in `hack_identifier'. */
3204: if (TREE_CODE (id) == CONST_DECL)
3205: {
3206: if (IDENTIFIER_CLASS_VALUE (token) == id)
3207: {
3208: /* Check access. */
3209: enum access_type access
3210: = compute_access (TYPE_BINFO (current_class_type), id);
3211: if (access == access_private)
3212: cp_error ("enum `%D' is private", id);
3213: /* protected is OK, since it's an enum of `this'. */
3214: }
3215: id = DECL_INITIAL (id);
3216: }
3217: else
3218: id = hack_identifier (id, token, yychar);
3219: return id;
3220: }
3221:
3222: tree
3223: identifier_typedecl_value (node)
3224: tree node;
3225: {
3226: tree t, type;
3227: type = IDENTIFIER_TYPE_VALUE (node);
3228: if (type == NULL_TREE)
3229: return NULL_TREE;
3230: #define do(X) \
3231: { \
3232: t = (X); \
3233: if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
3234: return t; \
3235: }
3236: do (IDENTIFIER_LOCAL_VALUE (node));
3237: do (IDENTIFIER_CLASS_VALUE (node));
3238: do (IDENTIFIER_GLOBAL_VALUE (node));
3239: #undef do
3240: /* Will this one ever happen? */
3241: if (TYPE_NAME (type))
3242: return TYPE_NAME (type);
3243:
3244: /* We used to do an internal error of 62 here, but instead we will
3245: handle the return of a null appropriately in the callers. */
3246: return NULL_TREE;
3247: }
3248:
3249: struct try_type
3250: {
3251: tree *node_var;
3252: char unsigned_flag;
3253: char long_flag;
3254: char long_long_flag;
3255: };
3256:
3257: struct try_type type_sequence[] =
3258: {
3259: { &integer_type_node, 0, 0, 0},
3260: { &unsigned_type_node, 1, 0, 0},
3261: { &long_integer_type_node, 0, 1, 0},
3262: { &long_unsigned_type_node, 1, 1, 0},
3263: { &long_long_integer_type_node, 0, 1, 1},
3264: { &long_long_unsigned_type_node, 1, 1, 1}
3265: };
3266:
3267: int
3268: real_yylex ()
3269: {
3270: register int c;
3271: register int value;
3272: int wide_flag = 0;
3273: int dollar_seen = 0;
3274: int i;
3275:
3276: if (nextchar >= 0)
3277: c = nextchar, nextchar = -1;
3278: else
3279: c = getch ();
3280:
3281: /* Effectively do c = skip_white_space (c)
3282: but do it faster in the usual cases. */
3283: while (1)
3284: switch (c)
3285: {
3286: case ' ':
3287: case '\t':
3288: case '\f':
3289: case '\v':
3290: case '\b':
3291: c = getch ();
3292: break;
3293:
3294: case '\r':
3295: /* Call skip_white_space so we can warn if appropriate. */
3296:
3297: case '\n':
3298: case '/':
3299: case '\\':
3300: c = skip_white_space (c);
3301: default:
3302: goto found_nonwhite;
3303: }
3304: found_nonwhite:
3305:
3306: token_buffer[0] = c;
3307: token_buffer[1] = 0;
3308:
3309: /* yylloc.first_line = lineno; */
3310:
3311: switch (c)
3312: {
3313: case EOF:
3314: token_buffer[0] = '\0';
3315: end_of_file = 1;
3316: if (input_redirected ())
3317: value = END_OF_SAVED_INPUT;
3318: else if (do_pending_expansions ())
3319: /* this will set yychar for us */
3320: return yychar;
3321: else
3322: value = ENDFILE;
3323: break;
3324:
3325: case '$':
3326: if (dollars_in_ident)
3327: {
3328: dollar_seen = 1;
3329: goto letter;
3330: }
3331: value = '$';
3332: goto done;
3333:
3334: case 'L':
3335: /* Capital L may start a wide-string or wide-character constant. */
3336: {
3337: register int c = getch ();
3338: if (c == '\'')
3339: {
3340: wide_flag = 1;
3341: goto char_constant;
3342: }
3343: if (c == '"')
3344: {
3345: wide_flag = 1;
3346: goto string_constant;
3347: }
3348: put_back (c);
3349: }
3350:
3351: case 'A': case 'B': case 'C': case 'D': case 'E':
3352: case 'F': case 'G': case 'H': case 'I': case 'J':
3353: case 'K': case 'M': case 'N': case 'O':
3354: case 'P': case 'Q': case 'R': case 'S': case 'T':
3355: case 'U': case 'V': case 'W': case 'X': case 'Y':
3356: case 'Z':
3357: case 'a': case 'b': case 'c': case 'd': case 'e':
3358: case 'f': case 'g': case 'h': case 'i': case 'j':
3359: case 'k': case 'l': case 'm': case 'n': case 'o':
3360: case 'p': case 'q': case 'r': case 's': case 't':
3361: case 'u': case 'v': case 'w': case 'x': case 'y':
3362: case 'z':
3363: case '_':
3364: letter:
3365: {
3366: register char *p;
3367:
3368: p = token_buffer;
3369: if (input == 0)
3370: {
3371: /* We know that `token_buffer' can hold at least on char,
3372: so we install C immediately.
3373: We may have to read the value in `putback_char', so call
3374: `getch' once. */
3375: *p++ = c;
3376: c = getch ();
3377:
3378: /* Make this run fast. We know that we are reading straight
3379: from FINPUT in this case (since identifiers cannot straddle
3380: input sources. */
3381: while (isalnum (c) || (c == '_') || c == '$')
3382: {
3383: if (c == '$' && ! dollars_in_ident)
3384: break;
3385: if (p >= token_buffer + maxtoken)
3386: p = extend_token_buffer (p);
3387:
3388: *p++ = c;
3389: c = getc (finput);
3390: }
3391: }
3392: else
3393: {
3394: /* We know that `token_buffer' can hold at least on char,
3395: so we install C immediately. */
3396: *p++ = c;
3397: c = getch ();
3398:
3399: while (isalnum (c) || (c == '_') || c == '$')
3400: {
3401: if (c == '$' && ! dollars_in_ident)
3402: break;
3403: if (p >= token_buffer + maxtoken)
3404: p = extend_token_buffer (p);
3405:
3406: *p++ = c;
3407: c = getch ();
3408: }
3409: }
3410:
3411: *p = 0;
3412: nextchar = c;
3413:
3414: value = IDENTIFIER;
3415: yylval.itype = 0;
3416:
3417: /* Try to recognize a keyword. Uses minimum-perfect hash function */
3418:
3419: {
3420: register struct resword *ptr;
3421:
3422: if (ptr = is_reserved_word (token_buffer, p - token_buffer))
3423: {
3424: if (ptr->rid)
3425: {
3426: tree old_ttype = ridpointers[(int) ptr->rid];
3427:
3428: /* If this provides a type for us, then revert lexical
3429: state to standard state. */
3430: if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
3431: && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
3432: && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
3433: looking_for_typename = 0;
3434: else if (ptr->token == AGGR || ptr->token == ENUM)
3435: looking_for_typename = 1;
3436:
3437: /* Check if this is a language-type declaration.
3438: Just glimpse the next non-white character. */
3439: nextchar = skip_white_space (nextchar);
3440: if (nextchar == '"')
3441: {
3442: /* We are looking at a string. Complain
3443: if the token before the string is no `extern'.
3444:
3445: Could cheat some memory by placing this string
3446: on the temporary_, instead of the saveable_
3447: obstack. */
3448:
3449: if (ptr->rid != RID_EXTERN)
3450: error ("invalid modifier `%s' for language string",
3451: ptr->name);
3452: real_yylex ();
3453: value = EXTERN_LANG_STRING;
3454: yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
3455: break;
3456: }
3457: if (ptr->token == VISSPEC)
3458: {
3459: switch (ptr->rid)
3460: {
3461: case RID_PUBLIC:
3462: yylval.itype = access_public;
3463: break;
3464: case RID_PRIVATE:
3465: yylval.itype = access_private;
3466: break;
3467: case RID_PROTECTED:
3468: yylval.itype = access_protected;
3469: break;
3470: default:
3471: my_friendly_abort (63);
3472: }
3473: }
3474: else
3475: yylval.ttype = old_ttype;
3476: }
3477: value = (int) ptr->token;
3478: }
3479: }
3480:
3481: /* If we did not find a keyword, look for an identifier
3482: (or a typename). */
3483:
3484: if (strcmp ("catch", token_buffer) == 0
3485: || strcmp ("throw", token_buffer) == 0
3486: || strcmp ("try", token_buffer) == 0)
3487: {
3488: static int did_warn = 0;
3489: if (! did_warn && ! flag_handle_exceptions)
3490: {
3491: pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
3492: did_warn = 1;
3493: }
3494: }
3495:
3496: if (value == IDENTIFIER || value == TYPESPEC)
3497: GNU_xref_ref (current_function_decl, token_buffer);
3498:
3499: if (value == IDENTIFIER)
3500: {
3501: register tree tmp = get_identifier (token_buffer);
3502:
3503: #if !defined(VMS) && defined(JOINER)
3504: /* Make sure that user does not collide with our internal
3505: naming scheme. */
3506: if (JOINER == '$'
3507: && dollar_seen
3508: && (THIS_NAME_P (tmp)
3509: || VPTR_NAME_P (tmp)
3510: || DESTRUCTOR_NAME_P (tmp)
3511: || VTABLE_NAME_P (tmp)
3512: || TEMP_NAME_P (tmp)
3513: || ANON_AGGRNAME_P (tmp)
3514: || ANON_PARMNAME_P (tmp)))
3515: warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
3516: token_buffer);
3517: #endif
3518:
3519: yylval.ttype = tmp;
3520:
3521: /* A user-invisible read-only initialized variable
3522: should be replaced by its value. We only handle strings
3523: since that's the only case used in C (and C++). */
3524: /* Note we go right after the local value for the identifier
3525: (e.g., __FUNCTION__ or __PRETTY_FUNCTION__). We used to
3526: call lookup_name, but that could result in an error about
3527: ambiguities. */
3528: tmp = IDENTIFIER_LOCAL_VALUE (yylval.ttype);
3529: if (tmp != NULL_TREE
3530: && TREE_CODE (tmp) == VAR_DECL
3531: && DECL_IGNORED_P (tmp)
3532: && TREE_READONLY (tmp)
3533: && DECL_INITIAL (tmp) != NULL_TREE
3534: && TREE_CODE (DECL_INITIAL (tmp)) == STRING_CST)
3535: {
3536: yylval.ttype = DECL_INITIAL (tmp);
3537: value = STRING;
3538: }
3539: }
3540: if (value == NEW && ! global_bindings_p ())
3541: {
3542: value = NEW;
3543: goto done;
3544: }
3545: }
3546: break;
3547:
3548: case '.':
3549: {
3550: register int c1 = getch ();
3551: token_buffer[0] = c;
3552: token_buffer[1] = c1;
3553: if (c1 == '*')
3554: {
3555: value = DOT_STAR;
3556: token_buffer[2] = 0;
3557: goto done;
3558: }
3559: if (c1 == '.')
3560: {
3561: c1 = getch ();
3562: if (c1 == '.')
3563: {
3564: token_buffer[2] = c1;
3565: token_buffer[3] = 0;
3566: value = ELLIPSIS;
3567: goto done;
3568: }
3569: error ("parse error at `..'");
3570: }
3571: if (isdigit (c1))
3572: {
3573: put_back (c1);
3574: goto resume_numerical_scan;
3575: }
3576: nextchar = c1;
3577: value = '.';
3578: token_buffer[1] = 0;
3579: goto done;
3580: }
3581: case '0': case '1':
3582: /* Optimize for most frequent case. */
3583: {
3584: register int c1 = getch ();
3585: if (! isalnum (c1) && c1 != '.')
3586: {
3587: /* Terminate string. */
3588: token_buffer[0] = c;
3589: token_buffer[1] = 0;
3590: if (c == '0')
3591: yylval.ttype = integer_zero_node;
3592: else
3593: yylval.ttype = integer_one_node;
3594: nextchar = c1;
3595: value = CONSTANT;
3596: goto done;
3597: }
3598: put_back (c1);
3599: }
3600: /* fall through... */
3601: case '2': case '3': case '4':
3602: case '5': case '6': case '7': case '8': case '9':
3603: resume_numerical_scan:
3604: {
3605: register char *p;
3606: int base = 10;
3607: int count = 0;
3608: int largest_digit = 0;
3609: int numdigits = 0;
3610: /* for multi-precision arithmetic,
3611: we actually store only HOST_BITS_PER_CHAR bits in each part.
3612: The number of parts is chosen so as to be sufficient to hold
3613: the enough bits to fit into the two HOST_WIDE_INTs that contain
3614: the integer value (this is always at least as many bits as are
3615: in a target `long long' value, but may be wider). */
3616: #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
3617: int parts[TOTAL_PARTS];
3618: int overflow = 0;
3619:
3620: enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
3621: = NOT_FLOAT;
3622:
3623: p = token_buffer;
3624: *p++ = c;
3625:
3626: for (count = 0; count < TOTAL_PARTS; count++)
3627: parts[count] = 0;
3628:
3629: if (c == '0')
3630: {
3631: *p++ = (c = getch ());
3632: if ((c == 'x') || (c == 'X'))
3633: {
3634: base = 16;
3635: *p++ = (c = getch ());
3636: }
3637: /* Leading 0 forces octal unless the 0 is the only digit. */
3638: else if (c >= '0' && c <= '9')
3639: {
3640: base = 8;
3641: numdigits++;
3642: }
3643: else
3644: numdigits++;
3645: }
3646:
3647: /* Read all the digits-and-decimal-points. */
3648:
3649: while (c == '.'
3650: || (isalnum (c) && (c != 'l') && (c != 'L')
3651: && (c != 'u') && (c != 'U')
3652: && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
3653: {
3654: if (c == '.')
3655: {
3656: if (base == 16)
3657: error ("floating constant may not be in radix 16");
3658: if (floatflag == AFTER_POINT)
3659: {
3660: error ("malformed floating constant");
3661: floatflag = TOO_MANY_POINTS;
3662: }
3663: else
3664: floatflag = AFTER_POINT;
3665:
3666: base = 10;
3667: *p++ = c = getch ();
3668: /* Accept '.' as the start of a floating-point number
3669: only when it is followed by a digit.
3670: Otherwise, unread the following non-digit
3671: and use the '.' as a structural token. */
3672: if (p == token_buffer + 2 && !isdigit (c))
3673: {
3674: if (c == '.')
3675: {
3676: c = getch ();
3677: if (c == '.')
3678: {
3679: *p++ = '.';
3680: *p = '\0';
3681: value = ELLIPSIS;
3682: goto done;
3683: }
3684: error ("parse error at `..'");
3685: }
3686: nextchar = c;
3687: token_buffer[1] = '\0';
3688: value = '.';
3689: goto done;
3690: }
3691: }
3692: else
3693: {
3694: /* It is not a decimal point.
3695: It should be a digit (perhaps a hex digit). */
3696:
3697: if (isdigit (c))
3698: {
3699: c = c - '0';
3700: }
3701: else if (base <= 10)
3702: {
3703: if (c == 'e' || c == 'E')
3704: {
3705: base = 10;
3706: floatflag = AFTER_POINT;
3707: break; /* start of exponent */
3708: }
3709: error ("nondigits in number and not hexadecimal");
3710: c = 0;
3711: }
3712: else if (c >= 'a')
3713: {
3714: c = c - 'a' + 10;
3715: }
3716: else
3717: {
3718: c = c - 'A' + 10;
3719: }
3720: if (c >= largest_digit)
3721: largest_digit = c;
3722: numdigits++;
3723:
3724: for (count = 0; count < TOTAL_PARTS; count++)
3725: {
3726: parts[count] *= base;
3727: if (count)
3728: {
3729: parts[count]
3730: += (parts[count-1] >> HOST_BITS_PER_CHAR);
3731: parts[count-1]
3732: &= (1 << HOST_BITS_PER_CHAR) - 1;
3733: }
3734: else
3735: parts[0] += c;
3736: }
3737:
3738: /* If the extra highest-order part ever gets anything in it,
3739: the number is certainly too big. */
3740: if (parts[TOTAL_PARTS - 1] != 0)
3741: overflow = 1;
3742:
3743: if (p >= token_buffer + maxtoken - 3)
3744: p = extend_token_buffer (p);
3745: *p++ = (c = getch ());
3746: }
3747: }
3748:
3749: if (numdigits == 0)
3750: error ("numeric constant with no digits");
3751:
3752: if (largest_digit >= base)
3753: error ("numeric constant contains digits beyond the radix");
3754:
3755: /* Remove terminating char from the token buffer and delimit the string */
3756: *--p = 0;
3757:
3758: if (floatflag != NOT_FLOAT)
3759: {
3760: tree type = double_type_node;
3761: char f_seen = 0;
3762: char l_seen = 0;
3763: int garbage_chars = 0;
3764: REAL_VALUE_TYPE value;
3765: jmp_buf handler;
3766:
3767: /* Read explicit exponent if any, and put it in tokenbuf. */
3768:
3769: if ((c == 'e') || (c == 'E'))
3770: {
3771: if (p >= token_buffer + maxtoken - 3)
3772: p = extend_token_buffer (p);
3773: *p++ = c;
3774: c = getch ();
3775: if ((c == '+') || (c == '-'))
3776: {
3777: *p++ = c;
3778: c = getch ();
3779: }
3780: if (! isdigit (c))
3781: error ("floating constant exponent has no digits");
3782: while (isdigit (c))
3783: {
3784: if (p >= token_buffer + maxtoken - 3)
3785: p = extend_token_buffer (p);
3786: *p++ = c;
3787: c = getch ();
3788: }
3789: }
3790:
3791: *p = 0;
3792: errno = 0;
3793:
3794: /* Convert string to a double, checking for overflow. */
3795: if (setjmp (handler))
3796: {
3797: error ("floating constant out of range");
3798: value = dconst0;
3799: }
3800: else
3801: {
3802: set_float_handler (handler);
3803: /* The second argument, machine_mode, of REAL_VALUE_ATOF
3804: tells the desired precision of the binary result of
3805: decimal-to-binary conversion. */
3806:
3807: /* Read the suffixes to choose a data type. */
3808: switch (c)
3809: {
3810: case 'f': case 'F':
3811: type = float_type_node;
3812: value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
3813: garbage_chars = -1;
3814: break;
3815:
3816: case 'l': case 'L':
3817: type = long_double_type_node;
3818: value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
3819: garbage_chars = -1;
3820: break;
3821:
3822: default:
3823: value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
3824: }
3825: set_float_handler (NULL_PTR);
3826: }
3827: if (pedantic
3828: && (REAL_VALUE_ISINF (value)
3829: #ifdef ERANGE
3830: || (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
3831: && errno == ERANGE
3832: /* ERANGE is also reported for underflow, so test the
3833: value to distinguish overflow from that. */
3834: && (REAL_VALUES_LESS (dconst1, value)
3835: || REAL_VALUES_LESS (value, dconstm1)))
3836: #endif
3837: ))
3838: {
3839: pedwarn ("floating point number exceeds range of `%s'",
3840: IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
3841: }
3842: /* Note: garbage_chars is -1 if first char is *not* garbage. */
3843: while (isalnum (c))
3844: {
3845: if (c == 'f' || c == 'F')
3846: {
3847: if (f_seen)
3848: error ("two `f's in floating constant");
3849: f_seen = 1;
3850: }
3851: if (c == 'l' || c == 'L')
3852: {
3853: if (l_seen)
3854: error ("two `l's in floating constant");
3855: l_seen = 1;
3856: }
3857: if (p >= token_buffer + maxtoken - 3)
3858: p = extend_token_buffer (p);
3859: *p++ = c;
3860: c = getch ();
3861: garbage_chars++;
3862: }
3863:
3864: if (garbage_chars > 0)
3865: error ("garbage at end of number");
3866:
3867: /* Create a node with determined type and value. */
3868: yylval.ttype = build_real (type, value);
3869:
3870: put_back (c);
3871: *p = 0;
3872: }
3873: else
3874: {
3875: tree type;
3876: HOST_WIDE_INT high, low;
3877: int spec_unsigned = 0;
3878: int spec_long = 0;
3879: int spec_long_long = 0;
3880: int bytes, warn;
3881:
3882: while (1)
3883: {
3884: if (c == 'u' || c == 'U')
3885: {
3886: if (spec_unsigned)
3887: error ("two `u's in integer constant");
3888: spec_unsigned = 1;
3889: }
3890: else if (c == 'l' || c == 'L')
3891: {
3892: if (spec_long)
3893: {
3894: if (spec_long_long)
3895: error ("three `l's in integer constant");
3896: else if (pedantic)
3897: pedwarn ("ANSI C++ forbids long long integer constants");
3898: spec_long_long = 1;
3899: }
3900: spec_long = 1;
3901: }
3902: else
3903: {
3904: if (isalnum (c))
3905: {
3906: error ("garbage at end of number");
3907: while (isalnum (c))
3908: {
3909: if (p >= token_buffer + maxtoken - 3)
3910: p = extend_token_buffer (p);
3911: *p++ = c;
3912: c = getch ();
3913: }
3914: }
3915: break;
3916: }
3917: if (p >= token_buffer + maxtoken - 3)
3918: p = extend_token_buffer (p);
3919: *p++ = c;
3920: c = getch ();
3921: }
3922:
3923: put_back (c);
3924:
3925: /* If the constant is not long long and it won't fit in an
3926: unsigned long, or if the constant is long long and won't fit
3927: in an unsigned long long, then warn that the constant is out
3928: of range. */
3929:
3930: /* ??? This assumes that long long and long integer types are
3931: a multiple of 8 bits. This better than the original code
3932: though which assumed that long was exactly 32 bits and long
3933: long was exactly 64 bits. */
3934:
3935: if (spec_long_long)
3936: bytes = TYPE_PRECISION (long_long_integer_type_node) / 8;
3937: else
3938: bytes = TYPE_PRECISION (long_integer_type_node) / 8;
3939:
3940: warn = overflow;
3941: for (i = bytes; i < TOTAL_PARTS; i++)
3942: if (parts[i])
3943: warn = 1;
3944: if (warn)
3945: pedwarn ("integer constant out of range");
3946:
3947: /* This is simplified by the fact that our constant
3948: is always positive. */
3949: high = low = 0;
3950:
3951: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
3952: {
3953: high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
3954: / HOST_BITS_PER_CHAR)]
3955: << (i * HOST_BITS_PER_CHAR));
3956: low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
3957: }
3958:
3959:
3960: yylval.ttype = build_int_2 (low, high);
3961: TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
3962:
3963: #if 0
3964: /* Find the first allowable type that the value fits in. */
3965: type = 0;
3966: for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
3967: i++)
3968: if (!(spec_long && !type_sequence[i].long_flag)
3969: && !(spec_long_long && !type_sequence[i].long_long_flag)
3970: && !(spec_unsigned && !type_sequence[i].unsigned_flag)
3971: /* A hex or octal constant traditionally is unsigned. */
3972: && !(base != 10 && flag_traditional
3973: && !type_sequence[i].unsigned_flag)
3974: /* A decimal constant can't be unsigned int
3975: unless explicitly specified. */
3976: && !(base == 10 && !spec_unsigned
3977: && *type_sequence[i].node_var == unsigned_type_node))
3978: if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
3979: {
3980: type = *type_sequence[i].node_var;
3981: break;
3982: }
3983: if (flag_traditional && type == long_unsigned_type_node
3984: && !spec_unsigned)
3985: type = long_integer_type_node;
3986:
3987: if (type == 0)
3988: {
3989: type = long_long_integer_type_node;
3990: warning ("integer constant out of range");
3991: }
3992:
3993: /* Warn about some cases where the type of a given constant
3994: changes from traditional C to ANSI C. */
3995: if (warn_traditional)
3996: {
3997: tree other_type = 0;
3998:
3999: /* This computation is the same as the previous one
4000: except that flag_traditional is used backwards. */
4001: for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
4002: i++)
4003: if (!(spec_long && !type_sequence[i].long_flag)
4004: && !(spec_long_long && !type_sequence[i].long_long_flag)
4005: && !(spec_unsigned && !type_sequence[i].unsigned_flag)
4006: /* A hex or octal constant traditionally is unsigned. */
4007: && !(base != 10 && !flag_traditional
4008: && !type_sequence[i].unsigned_flag)
4009: /* A decimal constant can't be unsigned int
4010: unless explicitly specified. */
4011: && !(base == 10 && !spec_unsigned
4012: && *type_sequence[i].node_var == unsigned_type_node))
4013: if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
4014: {
4015: other_type = *type_sequence[i].node_var;
4016: break;
4017: }
4018: if (!flag_traditional && type == long_unsigned_type_node
4019: && !spec_unsigned)
4020: type = long_integer_type_node;
4021:
4022: if (other_type != 0 && other_type != type)
4023: {
4024: if (flag_traditional)
4025: warning ("type of integer constant would be different without -traditional");
4026: else
4027: warning ("type of integer constant would be different with -traditional");
4028: }
4029: }
4030:
4031: #else /* 1 */
4032: if (!spec_long && !spec_unsigned
4033: && !(flag_traditional && base != 10)
4034: && int_fits_type_p (yylval.ttype, integer_type_node))
4035: {
4036: #if 0
4037: if (warn_traditional && base != 10)
4038: warning ("small nondecimal constant becomes signed in ANSI C++");
4039: #endif
4040: type = integer_type_node;
4041: }
4042: else if (!spec_long && (base != 10 || spec_unsigned)
4043: && int_fits_type_p (yylval.ttype, unsigned_type_node))
4044: {
4045: /* Nondecimal constants try unsigned even in traditional C. */
4046: type = unsigned_type_node;
4047: }
4048:
4049: else if (!spec_unsigned && !spec_long_long
4050: && int_fits_type_p (yylval.ttype, long_integer_type_node))
4051: type = long_integer_type_node;
4052:
4053: else if (! spec_long_long
4054: && int_fits_type_p (yylval.ttype,
4055: long_unsigned_type_node))
4056: {
4057: #if 0
4058: if (warn_traditional && !spec_unsigned)
4059: warning ("large integer constant becomes unsigned in ANSI C++");
4060: #endif
4061: if (flag_traditional && !spec_unsigned)
4062: type = long_integer_type_node;
4063: else
4064: type = long_unsigned_type_node;
4065: }
4066:
4067: else if (! spec_unsigned
4068: /* Verify value does not overflow into sign bit. */
4069: && TREE_INT_CST_HIGH (yylval.ttype) >= 0
4070: && int_fits_type_p (yylval.ttype,
4071: long_long_integer_type_node))
4072: type = long_long_integer_type_node;
4073:
4074: else if (int_fits_type_p (yylval.ttype,
4075: long_long_unsigned_type_node))
4076: {
4077: #if 0
4078: if (warn_traditional && !spec_unsigned)
4079: warning ("large nondecimal constant is unsigned in ANSI C++");
4080: #endif
4081:
4082: if (flag_traditional && !spec_unsigned)
4083: type = long_long_integer_type_node;
4084: else
4085: type = long_long_unsigned_type_node;
4086: }
4087:
4088: else
4089: {
4090: type = long_long_integer_type_node;
4091: warning ("integer constant out of range");
4092:
4093: if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
4094: warning ("decimal integer constant is so large that it is unsigned");
4095: }
4096: #endif
4097:
4098: TREE_TYPE (yylval.ttype) = type;
4099: *p = 0;
4100: }
4101:
4102: value = CONSTANT; break;
4103: }
4104:
4105: case '\'':
4106: char_constant:
4107: {
4108: register int result = 0;
4109: register int num_chars = 0;
4110: unsigned width = TYPE_PRECISION (char_type_node);
4111: int max_chars;
4112:
4113: if (wide_flag)
4114: {
4115: width = WCHAR_TYPE_SIZE;
4116: #ifdef MULTIBYTE_CHARS
4117: max_chars = MB_CUR_MAX;
4118: #else
4119: max_chars = 1;
4120: #endif
4121: }
4122: else
4123: max_chars = TYPE_PRECISION (integer_type_node) / width;
4124:
4125: while (1)
4126: {
4127: tryagain:
4128:
4129: c = getch ();
4130:
4131: if (c == '\'' || c == EOF)
4132: break;
4133:
4134: if (c == '\\')
4135: {
4136: int ignore = 0;
4137: c = readescape (&ignore);
4138: if (ignore)
4139: goto tryagain;
4140: if (width < HOST_BITS_PER_INT
4141: && (unsigned) c >= (1 << width))
4142: pedwarn ("escape sequence out of range for character");
4143: #ifdef MAP_CHARACTER
4144: if (isprint (c))
4145: c = MAP_CHARACTER (c);
4146: #endif
4147: }
4148: else if (c == '\n')
4149: {
4150: if (pedantic)
4151: pedwarn ("ANSI C++ forbids newline in character constant");
4152: lineno++;
4153: }
4154: #ifdef MAP_CHARACTER
4155: else
4156: c = MAP_CHARACTER (c);
4157: #endif
4158:
4159: num_chars++;
4160: if (num_chars > maxtoken - 4)
4161: extend_token_buffer (token_buffer);
4162:
4163: token_buffer[num_chars] = c;
4164:
4165: /* Merge character into result; ignore excess chars. */
4166: if (num_chars < max_chars + 1)
4167: {
4168: if (width < HOST_BITS_PER_INT)
4169: result = (result << width) | (c & ((1 << width) - 1));
4170: else
4171: result = c;
4172: }
4173: }
4174:
4175: token_buffer[num_chars + 1] = '\'';
4176: token_buffer[num_chars + 2] = 0;
4177:
4178: if (c != '\'')
4179: error ("malformatted character constant");
4180: else if (num_chars == 0)
4181: error ("empty character constant");
4182: else if (num_chars > max_chars)
4183: {
4184: num_chars = max_chars;
4185: error ("character constant too long");
4186: }
4187: else if (num_chars != 1 && ! flag_traditional)
4188: warning ("multi-character character constant");
4189:
4190: /* If char type is signed, sign-extend the constant. */
4191: if (! wide_flag)
4192: {
4193: int num_bits = num_chars * width;
4194: if (num_bits == 0)
4195: /* We already got an error; avoid invalid shift. */
4196: yylval.ttype = build_int_2 (0, 0);
4197: else if (TREE_UNSIGNED (char_type_node)
4198: || ((result >> (num_bits - 1)) & 1) == 0)
4199: yylval.ttype
4200: = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
4201: >> (HOST_BITS_PER_WIDE_INT - num_bits)),
4202: 0);
4203: else
4204: yylval.ttype
4205: = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
4206: >> (HOST_BITS_PER_WIDE_INT - num_bits)),
4207: -1);
4208: if (num_chars<=1)
4209: TREE_TYPE (yylval.ttype) = char_type_node;
4210: else
4211: TREE_TYPE (yylval.ttype) = integer_type_node;
4212: }
4213: else
4214: {
4215: #ifdef MULTIBYTE_CHARS
4216: /* Set the initial shift state and convert the next sequence. */
4217: result = 0;
4218: /* In all locales L'\0' is zero and mbtowc will return zero,
4219: so don't use it. */
4220: if (num_chars > 1
4221: || (num_chars == 1 && token_buffer[1] != '\0'))
4222: {
4223: wchar_t wc;
4224: (void) mbtowc (NULL, NULL, 0);
4225: if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
4226: result = wc;
4227: else
4228: warning ("Ignoring invalid multibyte character");
4229: }
4230: #endif
4231: yylval.ttype = build_int_2 (result, 0);
4232: TREE_TYPE (yylval.ttype) = wchar_type_node;
4233: }
4234:
4235: value = CONSTANT;
4236: break;
4237: }
4238:
4239: case '"':
4240: string_constant:
4241: {
4242: register char *p;
4243:
4244: c = getch ();
4245: p = token_buffer + 1;
4246:
4247: while (c != '"' && c >= 0)
4248: {
4249: /* ignore_escape_flag is set for reading the filename in #line. */
4250: if (!ignore_escape_flag && c == '\\')
4251: {
4252: int ignore = 0;
4253: c = readescape (&ignore);
4254: if (ignore)
4255: goto skipnewline;
4256: if (!wide_flag
4257: && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
4258: && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
4259: pedwarn ("escape sequence out of range for character");
4260: }
4261: else if (c == '\n')
4262: {
4263: if (pedantic)
4264: pedwarn ("ANSI C++ forbids newline in string constant");
4265: lineno++;
4266: }
4267:
4268: if (p == token_buffer + maxtoken)
4269: p = extend_token_buffer (p);
4270: *p++ = c;
4271:
4272: skipnewline:
4273: c = getch ();
4274: if (c == EOF) {
4275: error("Unterminated string");
4276: break;
4277: }
4278: }
4279: *p = 0;
4280:
4281: /* We have read the entire constant.
4282: Construct a STRING_CST for the result. */
4283:
4284: if (wide_flag)
4285: {
4286: /* If this is a L"..." wide-string, convert the multibyte string
4287: to a wide character string. */
4288: char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
4289: int len;
4290:
4291: #ifdef MULTIBYTE_CHARS
4292: len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
4293: if (len < 0 || len >= (p - token_buffer))
4294: {
4295: warning ("Ignoring invalid multibyte string");
4296: len = 0;
4297: }
4298: bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
4299: #else
4300: {
4301: union { long l; char c[sizeof (long)]; } u;
4302: int big_endian;
4303: char *wp, *cp;
4304:
4305: /* Determine whether host is little or big endian. */
4306: u.l = 1;
4307: big_endian = u.c[sizeof (long) - 1];
4308: wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0);
4309:
4310: bzero (widep, (p - token_buffer) * WCHAR_BYTES);
4311: for (cp = token_buffer + 1; cp < p; cp++)
4312: *wp = *cp, wp += WCHAR_BYTES;
4313: len = p - token_buffer - 1;
4314: }
4315: #endif
4316: yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
4317: TREE_TYPE (yylval.ttype) = wchar_array_type_node;
4318: }
4319: else
4320: {
4321: yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
4322: TREE_TYPE (yylval.ttype) = char_array_type_node;
4323: }
4324:
4325: *p++ = '"';
4326: *p = 0;
4327:
4328: value = STRING; break;
4329: }
4330:
4331: case '+':
4332: case '-':
4333: case '&':
4334: case '|':
4335: case '<':
4336: case '>':
4337: case '*':
4338: case '/':
4339: case '%':
4340: case '^':
4341: case '!':
4342: case '=':
4343: {
4344: register int c1;
4345:
4346: combine:
4347:
4348: switch (c)
4349: {
4350: case '+':
4351: yylval.code = PLUS_EXPR; break;
4352: case '-':
4353: yylval.code = MINUS_EXPR; break;
4354: case '&':
4355: yylval.code = BIT_AND_EXPR; break;
4356: case '|':
4357: yylval.code = BIT_IOR_EXPR; break;
4358: case '*':
4359: yylval.code = MULT_EXPR; break;
4360: case '/':
4361: yylval.code = TRUNC_DIV_EXPR; break;
4362: case '%':
4363: yylval.code = TRUNC_MOD_EXPR; break;
4364: case '^':
4365: yylval.code = BIT_XOR_EXPR; break;
4366: case LSHIFT:
4367: yylval.code = LSHIFT_EXPR; break;
4368: case RSHIFT:
4369: yylval.code = RSHIFT_EXPR; break;
4370: case '<':
4371: yylval.code = LT_EXPR; break;
4372: case '>':
4373: yylval.code = GT_EXPR; break;
4374: }
4375:
4376: token_buffer[1] = c1 = getch ();
4377: token_buffer[2] = 0;
4378:
4379: if (c1 == '=')
4380: {
4381: switch (c)
4382: {
4383: case '<':
4384: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
4385: case '>':
4386: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
4387: case '!':
4388: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
4389: case '=':
4390: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
4391: }
4392: value = ASSIGN; goto done;
4393: }
4394: else if (c == c1)
4395: switch (c)
4396: {
4397: case '+':
4398: value = PLUSPLUS; goto done;
4399: case '-':
4400: value = MINUSMINUS; goto done;
4401: case '&':
4402: value = ANDAND; goto done;
4403: case '|':
4404: value = OROR; goto done;
4405: case '<':
4406: c = LSHIFT;
4407: goto combine;
4408: case '>':
4409: c = RSHIFT;
4410: goto combine;
4411: }
4412: else if ((c == '-') && (c1 == '>'))
4413: {
4414: nextchar = skip_white_space (getch ());
4415: if (nextchar == '*')
4416: {
4417: nextchar = -1;
4418: value = POINTSAT_STAR;
4419: }
4420: else
4421: value = POINTSAT;
4422: goto done;
4423: }
4424: else if (c1 == '?' && (c == '<' || c == '>'))
4425: {
4426: token_buffer[3] = 0;
4427:
4428: c1 = getch ();
4429: yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
4430: if (c1 == '=')
4431: {
4432: /* <?= or >?= expression. */
4433: token_buffer[2] = c1;
4434: value = ASSIGN;
4435: }
4436: else
4437: {
4438: value = MIN_MAX;
4439: nextchar = c1;
4440: }
4441: if (flag_ansi)
4442: pedwarn ("use of `operator %s' is not standard C++",
4443: token_buffer);
4444: goto done;
4445: }
4446:
4447: nextchar = c1;
4448: token_buffer[1] = 0;
4449:
4450: value = c;
4451: goto done;
4452: }
4453:
4454: case ':':
4455: c = getch ();
4456: if (c == ':')
4457: {
4458: token_buffer[1] = ':';
4459: token_buffer[2] = '\0';
4460: value = SCOPE;
4461: yylval.itype = 1;
4462: }
4463: else
4464: {
4465: nextchar = c;
4466: value = ':';
4467: }
4468: break;
4469:
4470: case 0:
4471: /* Don't make yyparse think this is eof. */
4472: value = 1;
4473: break;
4474:
4475: case '(':
4476: /* try, weakly, to handle casts to pointers to functions. */
4477: nextchar = skip_white_space (getch ());
4478: if (nextchar == '*')
4479: {
4480: int next_c = skip_white_space (getch ());
4481: if (next_c == ')')
4482: {
4483: nextchar = -1;
4484: yylval.ttype = build1 (INDIRECT_REF, 0, 0);
4485: value = PAREN_STAR_PAREN;
4486: }
4487: else
4488: {
4489: put_back (next_c);
4490: value = c;
4491: }
4492: }
4493: else if (nextchar == ')')
4494: {
4495: nextchar = -1;
4496: yylval.ttype = NULL_TREE;
4497: value = LEFT_RIGHT;
4498: }
4499: else value = c;
4500: break;
4501:
4502: default:
4503: value = c;
4504: }
4505:
4506: done:
4507: /* yylloc.last_line = lineno; */
4508: #ifdef GATHER_STATISTICS
4509: token_count[value] += 1;
4510: #endif
4511:
4512: return value;
4513: }
4514:
4515: typedef enum
4516: {
4517: d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
4518: id_kind, op_id_kind, perm_list_kind, temp_list_kind,
4519: vec_kind, x_kind, lang_decl, lang_type, all_kinds
4520: } tree_node_kind;
4521: extern int tree_node_counts[];
4522: extern int tree_node_sizes[];
4523: extern char *tree_node_kind_names[];
4524:
4525: /* Place to save freed lang_decls which were allocated on the
4526: permanent_obstack. @@ Not currently used. */
4527: tree free_lang_decl_chain;
4528:
4529: tree
4530: build_lang_decl (code, name, type)
4531: enum tree_code code;
4532: tree name;
4533: tree type;
4534: {
4535: register tree t = build_decl (code, name, type);
4536: struct obstack *obstack = current_obstack;
4537: register int i = sizeof (struct lang_decl) / sizeof (int);
4538: register int *pi;
4539:
4540: if (! TREE_PERMANENT (t))
4541: obstack = saveable_obstack;
4542: else
4543: /* Could be that saveable is permanent and current is not. */
4544: obstack = &permanent_obstack;
4545:
4546: if (free_lang_decl_chain && obstack == &permanent_obstack)
4547: {
4548: pi = (int *)free_lang_decl_chain;
4549: free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
4550: }
4551: else
4552: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
4553:
4554: while (i > 0)
4555: pi[--i] = 0;
4556:
4557: DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
4558: LANG_DECL_PERMANENT ((struct lang_decl *) pi)
4559: = obstack == &permanent_obstack;
4560: my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
4561: == TREE_PERMANENT (t), 234);
4562: DECL_MAIN_VARIANT (t) = t;
4563: if (current_lang_name == lang_name_cplusplus)
4564: {
4565: DECL_LANGUAGE (t) = lang_cplusplus;
4566: #if 0
4567: #ifndef NO_AUTO_OVERLOAD
4568: if (code == FUNCTION_DECL && name != 0
4569: && ! (IDENTIFIER_LENGTH (name) == 4
4570: && IDENTIFIER_POINTER (name)[0] == 'm'
4571: && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
4572: && ! (IDENTIFIER_LENGTH (name) > 10
4573: && IDENTIFIER_POINTER (name)[0] == '_'
4574: && IDENTIFIER_POINTER (name)[1] == '_'
4575: && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
4576: TREE_OVERLOADED (name) = 1;
4577: #endif
4578: #endif
4579: }
4580: else if (current_lang_name == lang_name_c)
4581: DECL_LANGUAGE (t) = lang_c;
4582: else my_friendly_abort (64);
4583:
4584: #if 0 /* not yet, should get fixed properly later */
4585: if (code == TYPE_DECL)
4586: {
4587: tree id;
4588: id = get_identifier (build_overload_name (type, 1, 1));
4589: DECL_ASSEMBLER_NAME (t) = id;
4590: }
4591:
4592: #endif
4593: #ifdef GATHER_STATISTICS
4594: tree_node_counts[(int)lang_decl] += 1;
4595: tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
4596: #endif
4597:
4598: return t;
4599: }
4600:
4601: tree
4602: build_lang_field_decl (code, name, type)
4603: enum tree_code code;
4604: tree name;
4605: tree type;
4606: {
4607: extern struct obstack *current_obstack, *saveable_obstack;
4608: register tree t = build_decl (code, name, type);
4609: struct obstack *obstack = current_obstack;
4610: register int i = sizeof (struct lang_decl_flags) / sizeof (int);
4611: register int *pi;
4612: #if 0 /* not yet, should get fixed properly later */
4613:
4614: if (code == TYPE_DECL)
4615: {
4616: tree id;
4617: id = get_identifier (build_overload_name (type, 1, 1));
4618: DECL_ASSEMBLER_NAME (t) = id;
4619: }
4620: #endif
4621:
4622: if (! TREE_PERMANENT (t))
4623: obstack = saveable_obstack;
4624: else
4625: my_friendly_assert (obstack == &permanent_obstack, 235);
4626:
4627: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
4628: while (i > 0)
4629: pi[--i] = 0;
4630:
4631: DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
4632: return t;
4633: }
4634:
4635: void
4636: copy_lang_decl (node)
4637: tree node;
4638: {
4639: int size;
4640: int *pi;
4641:
4642: if (TREE_CODE (node) == FIELD_DECL)
4643: size = sizeof (struct lang_decl_flags);
4644: else
4645: size = sizeof (struct lang_decl);
4646: pi = (int *)obstack_alloc (&permanent_obstack, size);
4647: bcopy ((char *)DECL_LANG_SPECIFIC (node), (char *)pi, size);
4648: DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi;
4649: }
4650:
4651: tree
4652: make_lang_type (code)
4653: enum tree_code code;
4654: {
4655: extern struct obstack *current_obstack, *saveable_obstack;
4656: register tree t = make_node (code);
4657: struct obstack *obstack = current_obstack;
4658: register int i = sizeof (struct lang_type) / sizeof (int);
4659: register int *pi;
4660:
4661: /* Set up some flags that give proper default behavior. */
4662: IS_AGGR_TYPE (t) = 1;
4663:
4664: if (! TREE_PERMANENT (t))
4665: obstack = saveable_obstack;
4666: else
4667: my_friendly_assert (obstack == &permanent_obstack, 236);
4668:
4669: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
4670: while (i > 0)
4671: pi[--i] = 0;
4672:
4673: TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
4674: CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
4675: SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
4676: CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
4677: CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
4678: TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
4679: NULL_TREE);
4680: CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
4681:
4682: /* Make sure this is laid out, for ease of use later.
4683: In the presence of parse errors, the normal was of assuring
4684: this might not ever get executed, so we lay it out *immediately*. */
4685: build_pointer_type (t);
4686:
4687: #ifdef GATHER_STATISTICS
4688: tree_node_counts[(int)lang_type] += 1;
4689: tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
4690: #endif
4691:
4692: return t;
4693: }
4694:
4695: void
4696: copy_decl_lang_specific (decl)
4697: tree decl;
4698: {
4699: extern struct obstack *current_obstack, *saveable_obstack;
4700: register int *old = (int *)DECL_LANG_SPECIFIC (decl);
4701: struct obstack *obstack = current_obstack;
4702: register int i = sizeof (struct lang_decl) / sizeof (int);
4703: register int *pi;
4704:
4705: if (! TREE_PERMANENT (decl))
4706: obstack = saveable_obstack;
4707: else
4708: my_friendly_assert (obstack == &permanent_obstack, 237);
4709:
4710: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
4711: while (i-- > 0)
4712: pi[i] = old[i];
4713:
4714: DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
4715:
4716: #ifdef GATHER_STATISTICS
4717: tree_node_counts[(int)lang_decl] += 1;
4718: tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
4719: #endif
4720: }
4721:
4722: void
4723: dump_time_statistics ()
4724: {
4725: register tree prev = 0, decl, next;
4726: int this_time = my_get_run_time ();
4727: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
4728: += this_time - body_time;
4729:
4730: fprintf (stderr, "\n******\n");
4731: print_time ("header files (total)", header_time);
4732: print_time ("main file (total)", this_time - body_time);
4733: fprintf (stderr, "ratio = %g : 1\n",
4734: (double)header_time / (double)(this_time - body_time));
4735: fprintf (stderr, "\n******\n");
4736:
4737: for (decl = filename_times; decl; decl = next)
4738: {
4739: next = IDENTIFIER_GLOBAL_VALUE (decl);
4740: IDENTIFIER_GLOBAL_VALUE (decl) = prev;
4741: prev = decl;
4742: }
4743:
4744: for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
4745: print_time (IDENTIFIER_POINTER (decl),
4746: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
4747: }
4748:
4749: void
4750: compiler_error (s, v, v2)
4751: char *s;
4752: HOST_WIDE_INT v, v2; /* @@also used as pointer */
4753: {
4754: char buf[1024];
4755: sprintf (buf, s, v, v2);
4756: error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
4757: }
4758:
4759: void
4760: compiler_error_with_decl (decl, s)
4761: tree decl;
4762: char *s;
4763: {
4764: char *name;
4765: count_error (0);
4766:
4767: report_error_function (0);
4768:
4769: if (TREE_CODE (decl) == PARM_DECL)
4770: fprintf (stderr, "%s:%d: ",
4771: DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
4772: DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
4773: else
4774: fprintf (stderr, "%s:%d: ",
4775: DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
4776:
4777: name = lang_printable_name (decl);
4778: if (name)
4779: fprintf (stderr, s, name);
4780: else
4781: fprintf (stderr, s, "((anonymous))");
4782: fprintf (stderr, " (compiler error)\n");
4783: }
4784:
4785: void
4786: yyerror (string)
4787: char *string;
4788: {
4789: extern int end_of_file;
4790: char buf[200];
4791:
4792: strcpy (buf, string);
4793:
4794: /* We can't print string and character constants well
4795: because the token_buffer contains the result of processing escapes. */
4796: if (end_of_file)
4797: strcat (buf, input_redirected ()
4798: ? " at end of saved text"
4799: : " at end of input");
4800: else if (token_buffer[0] == 0)
4801: strcat (buf, " at null character");
4802: else if (token_buffer[0] == '"')
4803: strcat (buf, " before string constant");
4804: else if (token_buffer[0] == '\'')
4805: strcat (buf, " before character constant");
4806: else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
4807: sprintf (buf + strlen (buf), " before character 0%o",
4808: (unsigned char) token_buffer[0]);
4809: else
4810: strcat (buf, " before `%s'");
4811:
4812: error (buf, token_buffer);
4813: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.