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