|
|
1.1 ! root 1: /* Type Analyzer for GNU C++. ! 2: Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc. ! 3: Hacked... nay, bludgeoned... by Mark Eichin ([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 type analyzer for GNU C++. To debug it, define SPEW_DEBUG ! 23: when compiling cp-parse.c and cp-spew.c. */ ! 24: ! 25: #include "config.h" ! 26: #include <stdio.h> ! 27: #include "input.h" ! 28: #include "tree.h" ! 29: #include "cp-lex.h" ! 30: #ifdef OBJCPLUS ! 31: #include "obcp-parse.h" ! 32: #else ! 33: #include "cp-parse.h" ! 34: #endif ! 35: #include "cp-tree.h" ! 36: #include "flags.h" ! 37: #include "obstack.h" ! 38: ! 39: /* This takes a token stream that hasn't decided much about types and ! 40: tries to figure out as much as it can, with excessive lookahead and ! 41: backtracking. */ ! 42: ! 43: /* fifo of tokens recognized and available to parser. */ ! 44: struct token { ! 45: /* The values for YYCHAR will fit in a short. */ ! 46: short yychar; ! 47: short end_of_file; ! 48: YYSTYPE yylval; ! 49: }; ! 50: ! 51: static int do_aggr (); ! 52: static struct token frob_identifier (); ! 53: static struct token hack_scope (); ! 54: static tree hack_ptype (); ! 55: static tree hack_more_ids (); ! 56: ! 57: /* From cp-lex.c: */ ! 58: /* the declaration found for the last IDENTIFIER token read in. ! 59: yylex must look this up to detect typedefs, which get token type TYPENAME, ! 60: so it is left around in case the identifier is not a typedef but is ! 61: used in a context which makes it a reference to a variable. */ ! 62: extern tree lastiddecl; /* let our brains leak out here too */ ! 63: extern int yychar; /* the lookahead symbol */ ! 64: extern YYSTYPE yylval; /* the semantic value of the */ ! 65: /* lookahead symbol */ ! 66: extern int end_of_file; ! 67: ! 68: struct obstack token_obstack; ! 69: int first_token; ! 70: ! 71: #ifdef SPEW_DEBUG ! 72: int spew_debug = 0; ! 73: static unsigned int yylex_ctr = 0; ! 74: static int debug_yychar (); ! 75: #endif ! 76: ! 77: static char follows_typename[END_OF_SAVED_INPUT+1]; ! 78: static char follows_identifier[END_OF_SAVED_INPUT+1]; ! 79: ! 80: /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name ! 81: * of the last template_type parsed in cp-parse.y if it is followed by a ! 82: * scope operator. It will be reset inside the next invocation of yylex(). ! 83: * This is used for recognizing nested types inside templates. ! 84: * - [email protected] */ ! 85: tree template_type_seen_before_scope; ! 86: ! 87: /* Initialize token_obstack. Called once, from init_lex. */ ! 88: void ! 89: init_spew () ! 90: { ! 91: static char *chars_following_identifier = ".+-|/%^!?:"; ! 92: short *ps; ! 93: static short toks_follow_ids[] = ! 94: { ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE, ! 95: ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT, ! 96: POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF, ! 97: ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, ! 98: RETURN, GOTO, ASM_KEYWORD, GCC_ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF, ! 99: CLASSOF, ATTRIBUTE, AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT, ! 100: CATCH, THROW, ANSI_TRY, ANSI_THROW, DYNAMIC_CAST, TYPEID, ! 101: EXTERN_LANG_STRING, ALL, END_OF_SAVED_INPUT, -1 }; ! 102: static short toks_follow_types[] = ! 103: { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL, ! 104: ELLIPSIS, THIS, OPERATOR, TEMPLATE, SCOPE, START_DECLARATOR, ! 105: TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME, ! 106: PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 }; ! 107: ! 108: gcc_obstack_init(&token_obstack); ! 109: ! 110: /* Initialize the arrays saying what tokens are definitely ! 111: (or possibly) valid following typenames and identifiers. */ ! 112: while (*chars_following_identifier) ! 113: follows_identifier[*chars_following_identifier++] = 1; ! 114: for (ps = toks_follow_ids; *ps != -1; ps++) ! 115: follows_identifier[*ps] = 1; ! 116: for (ps = toks_follow_types; *ps != -1; ps++) ! 117: follows_typename[*ps] = 1; ! 118: } ! 119: ! 120: #ifdef SPEW_DEBUG ! 121: /* Use functions for debugging... */ ! 122: ! 123: /* Return the number of tokens available on the fifo. */ ! 124: static int ! 125: num_tokens () ! 126: { ! 127: return (obstack_object_size(&token_obstack)/sizeof(struct token)) ! 128: - first_token; ! 129: } ! 130: ! 131: /* Fetch the token N down the line from the head of the fifo. */ ! 132: static struct token* ! 133: nth_token (n) ! 134: int n; ! 135: { ! 136: /* could just have this do slurp_ implicitly, but this way is easier ! 137: * to debug... */ ! 138: my_friendly_assert (n < num_tokens(), 298); ! 139: return ((struct token*)obstack_base(&token_obstack))+n+first_token; ! 140: } ! 141: ! 142: /* Add a token to the token fifo. */ ! 143: static void ! 144: add_token (t) ! 145: struct token* t; ! 146: { ! 147: obstack_grow(&token_obstack,t,sizeof (struct token)); ! 148: } ! 149: ! 150: /* Consume the next token out of the fifo. */ ! 151: static void ! 152: consume_token() ! 153: { ! 154: if (num_tokens() == 1) ! 155: { ! 156: obstack_free(&token_obstack, obstack_base (&token_obstack)); ! 157: first_token = 0; ! 158: } ! 159: else ! 160: first_token++; ! 161: } ! 162: ! 163: #else ! 164: /* ...otherwise use macros. */ ! 165: ! 166: #define num_tokens() \ ! 167: ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token) ! 168: ! 169: #define nth_token(N) \ ! 170: (((struct token*)obstack_base(&token_obstack))+(N)+first_token) ! 171: ! 172: #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token)) ! 173: ! 174: #define consume_token() \ ! 175: (num_tokens() == 1 \ ! 176: ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \ ! 177: (first_token = 0)) \ ! 178: : first_token++) ! 179: #endif ! 180: ! 181: /* Pull in enough tokens from real_yylex that the queue is N long. */ ! 182: ! 183: static void ! 184: scan_tokens (n) ! 185: int n; ! 186: { ! 187: int i; ! 188: struct token *tmp; ! 189: ! 190: /* We cannot read past certain tokens, so make sure we don't. */ ! 191: i = num_tokens (); ! 192: if (i > n) ! 193: return; ! 194: while (i-- > 0) ! 195: { ! 196: tmp = nth_token (i); ! 197: /* Never read past these characters: they might separate ! 198: the current input stream from one we save away later. */ ! 199: if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';') ! 200: goto pad_tokens; ! 201: } ! 202: ! 203: while (num_tokens() <= n) ! 204: { ! 205: obstack_blank(&token_obstack,sizeof (struct token)); ! 206: tmp = ((struct token *)obstack_next_free (&token_obstack))-1; ! 207: tmp->yychar = real_yylex(); ! 208: tmp->end_of_file = end_of_file; ! 209: tmp->yylval = yylval; ! 210: end_of_file = 0; ! 211: if (tmp->yychar == '{' ! 212: || tmp->yychar == ':' ! 213: || tmp->yychar == ';') ! 214: { ! 215: pad_tokens: ! 216: while (num_tokens () <= n) ! 217: { ! 218: obstack_blank(&token_obstack,sizeof (struct token)); ! 219: tmp = ((struct token *)obstack_next_free (&token_obstack))-1; ! 220: tmp->yychar = EMPTY; ! 221: tmp->end_of_file = 0; ! 222: } ! 223: } ! 224: } ! 225: } ! 226: ! 227: /* Create room for N tokens at the front of the fifo. This is used ! 228: to insert new tokens into the stream ahead of the current token. */ ! 229: ! 230: static void ! 231: shift_tokens (n) ! 232: int n; ! 233: { ! 234: if (first_token >= n) ! 235: first_token -= n; ! 236: else ! 237: { ! 238: int old_token_count = num_tokens (); ! 239: char *tmp; ! 240: ! 241: obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token)); ! 242: if (old_token_count) ! 243: { ! 244: tmp = (char *)alloca ((num_tokens () + (n-first_token)) ! 245: * sizeof (struct token)); ! 246: /* This move does not rely on the system being able to handle ! 247: overlapping moves. */ ! 248: bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token)); ! 249: bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token)); ! 250: } ! 251: first_token = 0; ! 252: } ! 253: } ! 254: ! 255: static int ! 256: probe_obstack (h, obj, nlevels) ! 257: struct obstack *h; ! 258: tree obj; ! 259: unsigned int nlevels; ! 260: { ! 261: register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ ! 262: register struct _obstack_chunk* plp; /* point to previous chunk if any */ ! 263: ! 264: lp = (h)->chunk; ! 265: /* We use >= rather than > since the object cannot be exactly at ! 266: the beginning of the chunk but might be an empty object exactly ! 267: at the end of an adjacent chunk. */ ! 268: for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj); ! 269: nlevels -= 1) ! 270: { ! 271: plp = lp->prev; ! 272: lp = plp; ! 273: } ! 274: return nlevels != 0 && lp != 0; ! 275: } ! 276: ! 277: /* from cp-lex.c: */ ! 278: /* Value is 1 if we should try to make the next identifier look like a ! 279: typename (when it may be a local variable or a class variable). ! 280: Value is 0 if we treat this name in a default fashion. ! 281: Value is -1 if we must not see a type name. */ ! 282: extern int looking_for_typename; ! 283: ! 284: extern struct obstack *current_obstack, *saveable_obstack; ! 285: ! 286: int ! 287: yylex() ! 288: { ! 289: struct token tmp_token; ! 290: tree trrr; ! 291: ! 292: retry: ! 293: #ifdef SPEW_DEBUG ! 294: if (spew_debug) ! 295: { ! 296: yylex_ctr ++; ! 297: fprintf(stderr, "\t\t## %d ##",yylex_ctr); ! 298: } ! 299: #endif ! 300: ! 301: /* This is a kludge for recognizing nested types in templates */ ! 302: if (template_type_seen_before_scope) ! 303: { ! 304: shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */ ! 305: nth_token (1)->yychar = SCOPE; ! 306: yylval.ttype = hack_more_ids (0, template_type_seen_before_scope); ! 307: template_type_seen_before_scope = 0; ! 308: if (!yylval.ttype) ! 309: { ! 310: /* Sync back again, leaving SCOPE on the token stream, because we ! 311: * failed to substitute the original SCOPE token with a ! 312: * SCOPED_TYPENAME. See rule "template_type" in cp-parse.y */ ! 313: consume_token (); ! 314: } ! 315: else ! 316: { ! 317: yychar = SCOPED_TYPENAME; ! 318: #ifdef SPEW_DEBUG ! 319: if (spew_debug) ! 320: debug_yychar(yychar); ! 321: #endif ! 322: return yychar; ! 323: } ! 324: } ! 325: ! 326: /* if we've got tokens, send them */ ! 327: if (num_tokens()) ! 328: { ! 329: tmp_token= *nth_token(0); ! 330: ! 331: /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack. ! 332: If we don't find it in CURRENT_OBSTACK's current or immediately ! 333: previous chunk, assume it was and copy it to the current obstack. */ ! 334: if ((tmp_token.yychar == CONSTANT ! 335: || tmp_token.yychar == STRING) ! 336: && ! TREE_PERMANENT (tmp_token.yylval.ttype) ! 337: && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2) ! 338: && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2)) ! 339: tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype); ! 340: } ! 341: else ! 342: { ! 343: /* if not, grab the next one and think about it */ ! 344: tmp_token.yychar = real_yylex (); ! 345: tmp_token.yylval = yylval; ! 346: tmp_token.end_of_file = end_of_file; ! 347: add_token(&tmp_token); ! 348: } ! 349: ! 350: /* many tokens just need to be returned. At first glance, all we ! 351: * have to do is send them back up, but some of them are needed to ! 352: * figure out local context. */ ! 353: switch(tmp_token.yychar) ! 354: { ! 355: case EMPTY: ! 356: /* This is a lexical no-op. */ ! 357: consume_token (); ! 358: #ifdef SPEW_DEBUG ! 359: if (spew_debug) ! 360: debug_yychar (tmp_token.yychar); ! 361: #endif ! 362: goto retry; ! 363: ! 364: case IDENTIFIER: ! 365: /* Note: this calls arbitrate_lookup. */ ! 366: trrr = lookup_name (tmp_token.yylval.ttype, -2); ! 367: if (trrr) ! 368: { ! 369: tmp_token.yychar = identifier_type (trrr); ! 370: switch (tmp_token.yychar) ! 371: { ! 372: case TYPENAME: ! 373: lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype); ! 374: if (lastiddecl == NULL_TREE) ! 375: lastiddecl = trrr; ! 376: break; ! 377: case IDENTIFIER: ! 378: lastiddecl = trrr; ! 379: break; ! 380: case PTYPENAME: ! 381: /* This is for cases like ! 382: template<class A> X<A>::operator[] ... ! 383: since "X" is (presumably) a PTYPENAME; we might want to ! 384: avoid seeing the entire thing as a type name, but X<A> ! 385: must be one. ! 386: ! 387: It might not work right if the thing after the :: ! 388: can be a typename nested in X<A>, but I don't think the ! 389: PT code would be up to dealing with that anyways. --KR */ ! 390: if (looking_for_typename == -1) ! 391: { ! 392: scan_tokens (2); ! 393: if (nth_token(1)->yychar == '<') ! 394: looking_for_typename = 0; ! 395: } ! 396: break; ! 397: default: ! 398: my_friendly_abort (101); ! 399: } ! 400: } ! 401: else ! 402: lastiddecl = trrr; ! 403: /* and fall through to... */ ! 404: case TYPENAME: ! 405: case PTYPENAME: ! 406: /* if (new_token) add_token (&tmp_token); */ ! 407: *nth_token(0) = tmp_token; ! 408: tmp_token = frob_identifier (); ! 409: if (looking_for_typename < 0) ! 410: { ! 411: tmp_token.yychar = IDENTIFIER; ! 412: lastiddecl = 0; ! 413: looking_for_typename = 0; ! 414: } ! 415: else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL) ! 416: { ! 417: scan_tokens (2); ! 418: if (nth_token(0)->yychar == IDENTIFIER ! 419: && nth_token (1)->yychar != SCOPE) ! 420: looking_for_typename = -1; ! 421: else ! 422: looking_for_typename = 0; ! 423: goto finish_typename_processing; ! 424: } ! 425: else ! 426: looking_for_typename = 0; ! 427: break; ! 428: ! 429: case TYPESPEC: ! 430: case SCSPEC: ! 431: consume_token (); ! 432: finish_typename_processing: ! 433: /* Now see if we should insert a START_DECLARATOR token. ! 434: Here are the cases caught: ! 435: ! 436: typespec ( * ID ) ( // ptr to function ! 437: typespec ( & ID ) ( // ref to function ! 438: typespec ( * ID ) [ // array of pointers ! 439: typespec ( & ID ) [ // array of references ! 440: ! 441: This is a terrible kludge. */ ! 442: ! 443: scan_tokens (2); ! 444: if (nth_token (0)->yychar == '(' ! 445: && (nth_token (1)->yychar == '*' ! 446: || nth_token (1)->yychar == '&')) ! 447: { ! 448: scan_tokens (5); ! 449: if (nth_token (3)->yychar == ')' ! 450: && (nth_token (4)->yychar == '(' ! 451: || nth_token (4)->yychar == '[' ! 452: || nth_token (4)->yychar == LEFT_RIGHT) ! 453: && (nth_token (2)->yychar == IDENTIFIER ! 454: || nth_token (2)->yychar == TYPENAME)) ! 455: { ! 456: shift_tokens (1); ! 457: nth_token (0)->yychar = START_DECLARATOR; ! 458: } ! 459: } ! 460: /* Extend to handle: ! 461: ! 462: typespec (ID::* qf)( // ptr to member function ! 463: typespec (ID::* qf)[ // array of ptr to member functions ! 464: ! 465: */ ! 466: if (nth_token (0)->yychar == '(' ! 467: && (nth_token (1)->yychar == IDENTIFIER ! 468: || nth_token (1)->yychar == TYPENAME)) ! 469: { ! 470: scan_tokens (7); ! 471: if (nth_token (2)->yychar == SCOPE ! 472: && nth_token (3)->yychar == '*' ! 473: && (nth_token (4)->yychar == IDENTIFIER ! 474: || nth_token (4)->yychar == TYPENAME) ! 475: && nth_token (5)->yychar == ')' ! 476: && (nth_token (6)->yychar == '(' ! 477: || nth_token (6)->yychar == '[' ! 478: || nth_token (6)->yychar == LEFT_RIGHT)) ! 479: { ! 480: shift_tokens (1); ! 481: nth_token (0)->yychar = START_DECLARATOR; ! 482: } ! 483: } ! 484: break; ! 485: ! 486: #if 0 ! 487: case '(': ! 488: /* Handle casts. We are looking for one of: ! 489: `( TYPENAME' followed by `)', or ! 490: `( TYPENAME *' followed by one of `[,*,&,)', or ! 491: `( TYPENAME &' followed by one of `[,*,&,)', or ! 492: `( TYPENAME [' followed by `]'. We are punting ! 493: generality on scanning casts to array types. */ ! 494: scan_tokens (4); ! 495: if (nth_token (1)->yychar == IDENTIFIER) ! 496: { ! 497: tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype); ! 498: if (type) ! 499: switch (nth_token (2)->yychar) ! 500: { ! 501: default: ! 502: break; ! 503: } ! 504: } ! 505: break; ! 506: ! 507: case SCOPE: ! 508: /* if (new_token) add_token (&tmp_token); */ ! 509: *nth_token(0) = tmp_token; ! 510: tmp_token = hack_scope (); ! 511: break; ! 512: #endif ! 513: ! 514: case AGGR: ! 515: *nth_token(0) = tmp_token; ! 516: do_aggr (); ! 517: /* fall through to output... */ ! 518: case ENUM: ! 519: /* Set this again, in case we are rescanning. */ ! 520: looking_for_typename = 1; ! 521: /* fall through... */ ! 522: default: ! 523: #ifdef SPEW_DEBUG ! 524: if (spew_debug) ! 525: debug_yychar(tmp_token.yychar); ! 526: #endif ! 527: consume_token(); ! 528: yylval = tmp_token.yylval; ! 529: yychar = tmp_token.yychar; ! 530: end_of_file = tmp_token.end_of_file; ! 531: return tmp_token.yychar; ! 532: } ! 533: ! 534: if (tmp_token.yychar == SCOPED_TYPENAME) ! 535: { ! 536: #if 0 ! 537: tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype); ! 538: if (t2 != NULL_TREE) ! 539: { ! 540: tmp_token.yylval.ttype = t2; ! 541: tmp_token.yychar = TYPENAME; ! 542: } ! 543: else ! 544: { ! 545: /* unwind? */ ! 546: } ! 547: } ! 548: else ! 549: { ! 550: /* couldn't get here, as is... */ ! 551: #endif ! 552: tmp_token.yychar = TYPENAME; ! 553: } ! 554: ! 555: yylval = tmp_token.yylval; ! 556: yychar = tmp_token.yychar; ! 557: end_of_file = tmp_token.end_of_file; ! 558: #ifdef SPEW_DEBUG ! 559: if (spew_debug) ! 560: debug_yychar(yychar); ! 561: #endif ! 562: /* consume_token(); */ /* already eaten by frob_identifier?... */ ! 563: return yychar; ! 564: } ! 565: ! 566: /* token[0] == AGGR (struct/union/enum) ! 567: * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN ! 568: * if token[2] == '{' or ':' then it's TYPENAME_DEFN ! 569: */ ! 570: static int ! 571: do_aggr () ! 572: { ! 573: int yc1, yc2; ! 574: ! 575: scan_tokens (2); ! 576: yc1 = nth_token (1)->yychar; ! 577: if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME) ! 578: return 0; ! 579: yc2 = nth_token (2)->yychar; ! 580: if (yc2 == '{' || yc2 == ':') ! 581: { ! 582: switch (yc1) ! 583: { ! 584: case TYPENAME: ! 585: nth_token (1)->yychar = TYPENAME_DEFN; ! 586: break; ! 587: case PTYPENAME: ! 588: nth_token (1)->yychar = PTYPENAME_DEFN; ! 589: break; ! 590: case IDENTIFIER: ! 591: nth_token (1)->yychar = IDENTIFIER_DEFN; ! 592: break; ! 593: default: ! 594: my_friendly_abort (102); ! 595: } ! 596: } ! 597: return 0; ! 598: } ! 599: ! 600: static struct token ! 601: frob_identifier () ! 602: { ! 603: /* we could have a type, if it is followed by :: (if so, suck it all up); */ ! 604: /* we could have a ptypename; */ ! 605: /* we could have a normal identifier. */ ! 606: tree t1; ! 607: struct token rt; ! 608: ! 609: scan_tokens(1); ! 610: rt = *nth_token(0); ! 611: ! 612: #if 0 ! 613: if (nth_token(1)->yychar == '<') ! 614: { ! 615: t1 = hack_ptype(); /* suck up the whole thing */ ! 616: if (t1) ! 617: { ! 618: rt.yylval.ttype = t1; ! 619: rt.yychar = TYPENAME; ! 620: *nth_token(0) = rt; ! 621: } ! 622: /* else fall out bottom */ ! 623: } ! 624: #endif ! 625: ! 626: if (nth_token(1)->yychar == SCOPE) ! 627: { ! 628: #if 0 ! 629: t1 = hack_more_ids(0); ! 630: if (t1 && TREE_CODE(t1) == SCOPE_REF) ! 631: #else ! 632: t1 = hack_more_ids(0, nth_token (0)->yylval.ttype); ! 633: if (t1) ! 634: #endif ! 635: { ! 636: rt.yylval.ttype = t1; ! 637: rt.yychar = SCOPED_TYPENAME ; ! 638: return rt; ! 639: } ! 640: else ! 641: { ! 642: /* deal with types (enums?) in classes... */ ! 643: struct token *tok; ! 644: tree ta, tb; ! 645: scan_tokens(3); ! 646: ! 647: /* Have to check for a type conversion operator ! 648: to a nested type. */ ! 649: if (nth_token (2)->yychar == OPERATOR) ! 650: tok = nth_token (3); ! 651: else ! 652: tok = nth_token(2); ! 653: ! 654: if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME) ! 655: { ! 656: ta = build_parse_node (SCOPE_REF, ! 657: nth_token(0)->yylval.ttype, ! 658: tok->yylval.ttype); ! 659: tb = resolve_scope_to_name (NULL_TREE, ta); ! 660: ! 661: if (tb != NULL_TREE) ! 662: { ! 663: if (nth_token (2)->yychar == OPERATOR) ! 664: { ! 665: /* Have to keep these tokens around ! 666: so we can finish parsing the declaration. ! 667: What do we do for ! 668: ! 669: int foo::operator bar::baz (); ! 670: ! 671: where bar is a nested class in foo? */ ! 672: nth_token (3)->yychar = TYPENAME; ! 673: nth_token (3)->yylval.ttype = tb; ! 674: } ! 675: else ! 676: { ! 677: consume_token (); /* base type */ ! 678: consume_token (); /* SCOPE */ ! 679: consume_token (); /* member type */ ! 680: rt.yychar = TYPENAME; ! 681: rt.yylval.ttype = tb; ! 682: rt.end_of_file = tok->end_of_file; ! 683: return rt; ! 684: } ! 685: ! 686: } ! 687: } ! 688: /* else fall out bottom */ ! 689: } ! 690: } ! 691: ! 692: consume_token(); ! 693: return rt; ! 694: } ! 695: ! 696: /* When this function is called, nth_token(0) is the current ! 697: token we are scanning. This means that the next token we'll ! 698: scan is nth_token (1). Usually the next token we'll scan ! 699: is nth_token (0) (and the current token is in [yylval,yychar]). */ ! 700: tree ! 701: arbitrate_lookup (name, exp_decl, type_decl) ! 702: tree name, exp_decl, type_decl; ! 703: { ! 704: int ch; ! 705: tree t; ! 706: char *assume; ! 707: ! 708: scan_tokens (3); ! 709: ch = nth_token (1)->yychar; ! 710: ! 711: switch (ch) ! 712: { ! 713: case '(': ! 714: case LEFT_RIGHT: ! 715: /* If we guessed wrong here, `build_functional_cast' can fix it. */ ! 716: return type_decl; ! 717: ! 718: case '=': ! 719: if (global_bindings_p ()) ! 720: /* Probably a default parameter. */ ! 721: return type_decl; ! 722: /* Probably not an initialization. */ ! 723: return exp_decl; ! 724: ! 725: case '[': ! 726: /* This needs special help because an expression inside the ! 727: brackets means nothing. */ ! 728: { ! 729: int i; ! 730: ! 731: for (i = 0; i < 42; i++) ! 732: { ! 733: int ith_yychar; ! 734: ! 735: scan_tokens (3+i); ! 736: ith_yychar = nth_token (2+i)->yychar; ! 737: ! 738: /* If we hit an undefined identifier, assume ! 739: the decl in arbitration is its type specifier. */ ! 740: if (ith_yychar == IDENTIFIER ! 741: && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0) ! 742: return type_decl; ! 743: else if (ith_yychar == ']') ! 744: { ! 745: /* There are only a few things we expect after a ']' ! 746: in a declarator. */ ! 747: i += 1; ! 748: scan_tokens (4+i); ! 749: ith_yychar = nth_token (2+i)->yychar; ! 750: ! 751: /* These are inconclusive. */ ! 752: if (ith_yychar == LEFT_RIGHT ! 753: || ith_yychar == '(' ! 754: || ith_yychar == '[' ! 755: || ith_yychar == ',') ! 756: continue; ! 757: /* stmt or decl? We'll probably never know. */ ! 758: else if (ith_yychar == ';') ! 759: goto warn_ambiguous; ! 760: ! 761: if (ith_yychar == '=') ! 762: { ! 763: if (nth_token (3+i)->yychar == '{') ! 764: return type_decl; ! 765: continue; ! 766: } ! 767: ! 768: /* Whatever it is, it looks like we're processing an expr. */ ! 769: return exp_decl; ! 770: } ! 771: } ! 772: goto warn_ambiguous; ! 773: } ! 774: ! 775: case ',': ! 776: case ';': ! 777: case '&': ! 778: case '<': ! 779: case '*': ! 780: case ']': ! 781: case ')': ! 782: case '>': ! 783: /* see if the next token looks like it wants to be part ! 784: of a declaration list or an expression list. */ ! 785: { ! 786: int i; ! 787: ! 788: /* Some heuristics: if we are inside a function definition, ! 789: prefer the local declaration. */ ! 790: if (! global_bindings_p ()) ! 791: { ! 792: if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl) ! 793: return exp_decl; ! 794: if (IDENTIFIER_LOCAL_VALUE (name) != type_decl ! 795: && IDENTIFIER_CLASS_VALUE (name) == exp_decl) ! 796: return exp_decl; ! 797: } ! 798: /* If these symbols follow in a list, we know it's a list of ! 799: expressions. */ ! 800: if (follows_identifier[nth_token (2)->yychar]) ! 801: return exp_decl; ! 802: ! 803: /* If we see a id&, or id&) the we are probably in an argument list. */ ! 804: if (ch=='&' ! 805: && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')')) ! 806: return type_decl; ! 807: ! 808: /* Look for the first identifier or other distinguishing token ! 809: we find in the next several tokens. */ ! 810: for (i = 0; i < 42; i++) ! 811: { ! 812: int ith_yychar; ! 813: ! 814: scan_tokens (3+i); ! 815: ith_yychar = nth_token (2+i)->yychar; ! 816: ! 817: if (ith_yychar == IDENTIFIER) ! 818: { ! 819: tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1); ! 820: if (as_type && TREE_CODE (as_type) != TYPE_DECL) ! 821: return exp_decl; ! 822: /* An undeclared identifier or a typename means we're ! 823: probably looking at a typename. */ ! 824: return type_decl; ! 825: } ! 826: else if (ith_yychar == EMPTY ! 827: || follows_identifier[ith_yychar]) ! 828: return exp_decl; ! 829: else if (follows_typename[ith_yychar]) ! 830: return type_decl; ! 831: /* stmt or decl? We'll probably never know. */ ! 832: else if (ith_yychar == ';') ! 833: goto warn_ambiguous; ! 834: } ! 835: goto warn_ambiguous; ! 836: } ! 837: ! 838: default: ! 839: if (follows_identifier[ch]) ! 840: return exp_decl; ! 841: if (follows_typename[ch]) ! 842: return type_decl; ! 843: ! 844: /* Fall through... */ ! 845: warn_ambiguous: ! 846: if (ch == '[') ! 847: { ! 848: assume = "expression"; ! 849: t = exp_decl; ! 850: } ! 851: else ! 852: { ! 853: assume = "type"; ! 854: t = type_decl; ! 855: } ! 856: ! 857: warning ("name `%s' could be type or expression; compiler assuming %s", ! 858: IDENTIFIER_POINTER (DECL_NAME (t)), assume); ! 859: return t; ! 860: } ! 861: } ! 862: ! 863: /* now returns decl_node */ ! 864: ! 865: #if 0 ! 866: static tree ! 867: hack_ptype() ! 868: { ! 869: /* when we get here, we know that [0] is a ptype and [1] is '<'. ! 870: * now we loop over simple parameters. */ ! 871: struct token this_param; ! 872: int n = 2; ! 873: tree tplist = 0; ! 874: tree tc; ! 875: scan_tokens(n+1); ! 876: ! 877: while((this_param = *nth_token(n)).yychar != '>') ! 878: { ! 879: /* if it is a type, add it to the list */ ! 880: tree thistype; ! 881: ! 882: switch(this_param.yychar) ! 883: { ! 884: case IDENTIFIER: ! 885: case TYPENAME: ! 886: case TYPESPEC: ! 887: break; ! 888: default: ! 889: return 0; ! 890: } ! 891: ! 892: thistype = this_param.yylval.ttype; ! 893: thistype = lookup_name(thistype, 1); ! 894: thistype = TREE_TYPE (thistype); ! 895: ! 896: if (tplist) ! 897: tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype)); ! 898: else ! 899: tplist = build_tree_list(NULL_TREE, thistype); ! 900: ! 901: ! 902: /* then suck up the comma */ ! 903: n++; ! 904: scan_tokens(n+1); ! 905: this_param = *nth_token(n); ! 906: if (this_param.yychar == ',') ! 907: { ! 908: n++; ! 909: scan_tokens(n+1); ! 910: continue; ! 911: } ! 912: if (this_param.yychar == '>') ! 913: break; ! 914: return 0; ! 915: } ! 916: ! 917: /* once we're done, lookup_template_class -> identifier */ ! 918: tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist); ! 919: /* then lookup_name on that to get a type, if there is one */ ! 920: tc = lookup_name (tc, 1); ! 921: if (tc) ! 922: { ! 923: int i; ! 924: /* don't actually eat the trailing '>'... we can replace it! */ ! 925: for (i=0; i<n; i++) ! 926: consume_token(); ! 927: /* IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */ ! 928: return DECL_NAME (tc); ! 929: } ! 930: return NULL_TREE; ! 931: } ! 932: #endif ! 933: ! 934: #if 0 ! 935: static tree ! 936: hack_more_ids (n) ! 937: int n; ! 938: { ! 939: /* ! 940: * The recursion should probably do consume_tokens(), since once we've started ! 941: * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just ! 942: * get as much as we can, make SCOPE_REF's out of it, and return it. ! 943: */ ! 944: struct token this_iter, this2_iter; ! 945: int tmp_y; ! 946: ! 947: scan_tokens(n+1); ! 948: this_iter = *nth_token(n); ! 949: ! 950: tmp_y = nth_token(n)->yychar; ! 951: if (tmp_y == IDENTIFIER || tmp_y == TYPENAME) ! 952: { ! 953: scan_tokens(n+2+2); ! 954: if (nth_token(n+1)->yychar == SCOPE) ! 955: { ! 956: if (nth_token(n+1+2)->yychar == SCOPE) ! 957: { ! 958: tree hmi; ! 959: ! 960: consume_token(); /* last IDENTIFIER (this_iter) */ ! 961: consume_token(); /* last SCOPE */ ! 962: this2_iter = *nth_token(n); ! 963: ! 964: hmi = hack_more_ids (n); ! 965: ! 966: if (hmi) ! 967: return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi); ! 968: consume_token(); /* last IDENTIFIER (this2_iter) */ ! 969: return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, ! 970: this2_iter.yylval.ttype); ! 971: } ! 972: else ! 973: { ! 974: /* consume_token(); */ /* last IDENTIFIER */ ! 975: /* leave whatever else we got */ ! 976: /* return this_iter.yylval.ttype; */ ! 977: return NULL_TREE; ! 978: } ! 979: } ! 980: } ! 981: return NULL_TREE; /* @@ may need to backtrack */ ! 982: } ! 983: #else ! 984: /* [email protected] says: I didn't understand how the code above was intended ! 985: * to work, so I rewrote it (also changed the interface a bit). This code ! 986: * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed ! 987: * type prefix constitutes recognizable (by resolve_scope_to_name) types. ! 988: * Interface changed like this: ! 989: * 1. Takes an extra argument containing the name of the the type recognized ! 990: * so far. ! 991: * 2. Now returns the name of the type instead of a SCOPE_REF. */ ! 992: static tree ! 993: hack_more_ids(n, outer) ! 994: int n; ! 995: tree outer; ! 996: { ! 997: int ch; ! 998: tree type, val; ! 999: ! 1000: scan_tokens (n + 2); ! 1001: if (nth_token (n + 1)->yychar != SCOPE ! 1002: || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME)) ! 1003: return NULL_TREE; ! 1004: val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype); ! 1005: type = resolve_scope_to_name (NULL_TREE, val); ! 1006: if (type == NULL_TREE) ! 1007: return NULL_TREE; ! 1008: consume_token (); ! 1009: consume_token (); ! 1010: val = hack_more_ids (n, type); ! 1011: if (! val) ! 1012: consume_token (); ! 1013: return val ? val : type; ! 1014: } ! 1015: #endif ! 1016: ! 1017: #if 0 ! 1018: static struct token ! 1019: hack_scope () ! 1020: { ! 1021: /* we've got a :: - what follows is either a global var or a type. */ ! 1022: /* hmm, template names can be in the global scope too... */ ! 1023: tree t1; ! 1024: struct token rt; ! 1025: ! 1026: scan_tokens(1); ! 1027: if (nth_token(1)->yychar == IDENTIFIER) ! 1028: { ! 1029: /* @@ this is probably not right, but doesn't get hit yet */ ! 1030: t1 = build_parse_node (SCOPE_REF, ! 1031: NULL_TREE, /* to get "global" scope */ ! 1032: hack_more_ids(0)); /* do some prefetching */ ! 1033: rt.yylval.ttype = t1; ! 1034: rt.yychar = /*SCOPED_*/TYPENAME; ! 1035: return rt; ! 1036: } ! 1037: else ! 1038: { ! 1039: rt = *nth_token(0); ! 1040: consume_token(); ! 1041: return rt; ! 1042: } ! 1043: } ! 1044: #endif ! 1045: ! 1046: /* ! 1047: * Generations: ! 1048: * ! 1049: * PINST: PTYPE { saved_arg_count = arg_count($1) } ! 1050: * '<' { arg_c = 0; } PARGS '>' ! 1051: * ; ! 1052: * PARG: TYPE ! 1053: * | VALUE ! 1054: * ; ! 1055: * (of course the arg counting doesn't work for recursion... Do it right.) ! 1056: * PARGS: PARG { assert(arg_c == saved_arg_count); } ! 1057: * | PARG ',' PARGS { arg_c++; } ! 1058: * ; ! 1059: * ATYPE: PINST ! 1060: * | TYPEID ! 1061: * ; ! 1062: * TYPE: ATYPE ! 1063: * | ATYPE { basetype = $1; } '::' TYPEKIDS ! 1064: * ; ! 1065: * TYPEKIDS: TYPE { assert ($1 is a member of basetype); } ! 1066: * | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); } ! 1067: * ; ! 1068: * ! 1069: * ! 1070: * state0: ; ATYPE ! 1071: * TYPE '<': ac = args($0), base = CALL state1, state3 ! 1072: * TYPE '::': base=$0, state3 ! 1073: * else return TYPE ! 1074: * state1: ; begin PARGS ! 1075: * if(ac < list length) punt ! 1076: * PARG ",": add to list, state1 ! 1077: * PARG ">": add to list, return ! 1078: * else unravel ! 1079: * state3: ; begin TYPEKIDS ! 1080: * TYPE: ! 1081: */ ! 1082: ! 1083: ! 1084: #ifdef SPEW_DEBUG ! 1085: /* debug_yychar takes a yychar (token number) value and prints its name. */ ! 1086: static int ! 1087: debug_yychar (yy) ! 1088: int yy; ! 1089: { ! 1090: /* In cp-parse.y: */ ! 1091: extern char *debug_yytranslate (); ! 1092: ! 1093: int i; ! 1094: ! 1095: if(yy<256) { ! 1096: fprintf (stderr, "<%d: %c >\n", yy, yy); ! 1097: return 0; ! 1098: } ! 1099: fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy)); ! 1100: return 1; ! 1101: } ! 1102: ! 1103: #endif ! 1104: ! 1105: #ifdef OBJCPLUS ! 1106: /* Search the lookahead tokens for protocol qualifiers and change them into ! 1107: ordinary identifiers. */ ! 1108: void ! 1109: forget_saved_protocol_qualifiers () ! 1110: { ! 1111: ! 1112: int i; ! 1113: struct token *tmp; ! 1114: ! 1115: i = num_tokens (); ! 1116: while (i-- > 0) ! 1117: { ! 1118: tmp = nth_token (i); ! 1119: if (tmp->yychar == TYPE_QUAL ! 1120: && TREE_CODE (tmp->yylval.ttype) == IDENTIFIER_NODE) ! 1121: { ! 1122: char *name = IDENTIFIER_POINTER (tmp->yylval.ttype); ! 1123: if (strcmp (name, "in") == 0 ! 1124: || strcmp (name, "out") == 0 ! 1125: || strcmp (name, "inout") == 0 ! 1126: || strcmp (name, "bycopy") == 0 ! 1127: || strcmp (name, "oneway") == 0) ! 1128: tmp->yychar = IDENTIFIER; ! 1129: } ! 1130: } ! 1131: } ! 1132: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.