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