|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/lalex.c 1.6.3.37" */ ! 2: /************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: lalex.c: ! 11: ! 12: lookahead ! 13: ! 14: *****************************************************************************/ ! 15: #include <stdio.h> ! 16: ! 17: #ifdef c_plusplus ! 18: overload is_empty; ! 19: #endif ! 20: ! 21: #include "cfront.h" ! 22: #include "yystype.h" ! 23: #include "tqueue.h" ! 24: ! 25: #ifdef DBG ! 26: #define LDB(val,a) { if(Ldebug>=val) {a;} } ! 27: #else ! 28: #define LDB(val,a) /**/ ! 29: #endif ! 30: ! 31: #ifdef DBG ! 32: static char* ! 33: image( int t ) ! 34: { ! 35: if(keys[t]) return keys[t]; ! 36: else { static char b[20]; ! 37: sprintf(b,"token(%d)",t); ! 38: return b; ! 39: } ! 40: } ! 41: static void ! 42: showQ( char* where ) ! 43: /* ! 44: display token Q ! 45: */ ! 46: { ! 47: fprintf(stderr,"TOKEN Q (%s):\n",where); ! 48: for (register toknode* t = front; t; t = t->next) { ! 49: fprintf(stderr,"\t%s",image(t->tok)); ! 50: switch(t->tok) { ! 51: case ID: case ICON: case CCON: case FCON: case STRING: ! 52: fprintf(stderr," '%s'",t->retval.s); ! 53: break; ! 54: case TNAME: ! 55: fprintf(stderr," '%s'",t->retval.pn->string); ! 56: break; ! 57: } ! 58: putc(' ',stderr); ! 59: t->place.put(stderr); ! 60: putc('\n',stderr); ! 61: } ! 62: putc('\n',stderr); ! 63: } ! 64: #endif ! 65: ! 66: int bl_level; ! 67: ! 68: static int laexpr( TOK ); ! 69: static int latype( TOK ); ! 70: static int la_decl(); ! 71: static TOK lookahead(); ! 72: ! 73: /* make this a toknode! */ ! 74: static int lasttk = 0; // one token history ! 75: static YYSTYPE lastval; // yylval lasttk value ! 76: ! 77: int must_be_expr = 0; // handle redundant parentheses ! 78: int must_be_id = 0; // !0, TNAME => ID, i.e., int X ! 79: ! 80: loc curloc; ! 81: int curr_file; ! 82: ! 83: toknode* latok; // current lookahead token ! 84: toknode* front = 0; ! 85: toknode* rear = 0; ! 86: ! 87: static toknode* free_toks = 0; ! 88: const TQCHUNK = 16; ! 89: ! 90: toknode::toknode(TOK t, YYSTYPE r, loc tloc) ! 91: { ! 92: if (free_toks == 0) { ! 93: register toknode* q; ! 94: free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) ); ! 95: for (; q != &free_toks[TQCHUNK-1]; q->next = q+1, ++q); ! 96: q->next = 0; ! 97: } ! 98: this = free_toks; free_toks = free_toks->next; ! 99: tok = t; ! 100: used = 0; ! 101: retval = r; ! 102: place = tloc; ! 103: next = last = 0; ! 104: } ! 105: ! 106: toknode::~toknode() ! 107: { ! 108: next = free_toks; ! 109: free_toks = this; ! 110: this = 0; ! 111: } ! 112: ! 113: #define USE_TOKEN(T,W) \ ! 114: LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \ ! 115: if ( !(T)->used ) use_token(T); ! 116: ! 117: Ptype ! 118: return_nstd_local_type( Pname n, TOK &sw ) ! 119: { ! 120: Ptype tt; ! 121: switch ( n->tp->base ) { ! 122: case EOBJ: ! 123: case COBJ: ! 124: tt = Pbase(n->tp)->b_name->tp; ! 125: sw = n->tp->base; ! 126: break; ! 127: default: ! 128: tt = n->tpdef; ! 129: sw = NESTED; // in repr.c, prints ``typedef'' ! 130: break; ! 131: } ! 132: return tt; ! 133: } ! 134: ! 135: static Pname ! 136: local_nested_kludge( Pname n, Pname tn ) ! 137: /* ! 138: * for backward compatibility with 2.0 ! 139: * in transitional model of nested class types ! 140: * ! 141: * struct T { ... }; ! 142: * foobar() { ! 143: * class X { ! 144: * typedef int T; ! 145: * // ... ! 146: * }; ! 147: * T t; ! 148: * } ! 149: * ! 150: * pure nested classes, choose global struct T{}; ! 151: * no nested classes, choose typedef int T ! 152: * transitional model: choose typedef, and generate warning ! 153: * BUG: local typedefs and enums do not have lex_level set ! 154: */ ! 155: { ! 156: // error( 'd', "local_nested_kludge: n: %n", n ); ! 157: for ( Pname nn = n; nn; nn = nn->n_tbl_list ) ! 158: { ! 159: Pname local_class; ! 160: TOK ntd; ! 161: if ( nn->n_key != NESTED ) continue; ! 162: Ptype tt = return_nstd_local_type(nn,ntd); ! 163: Pclass cl = tt->in_class; ! 164: while ( cl->in_class ) cl = cl->in_class; ! 165: if (cl->lex_level && ! 166: (local_class = ktbl->look(cl->string,LOCAL))) ! 167: { ! 168: // same typedef at nested and non-nested scope ! 169: if (ntd == NESTED && tn && tn->tp == nn->tp ) ! 170: ; ! 171: else ! 172: error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string); ! 173: ! 174: /* ! 175: if ( ntd == NESTED && nn->n_dcl_printed != 2 ) { ! 176: nn->dcl_print(0); ! 177: nn->n_dcl_printed = 2; ! 178: } ! 179: */ ! 180: return nn; ! 181: } ! 182: } ! 183: return 0; ! 184: } ! 185: ! 186: enum { one_back, two_back }; ! 187: ! 188: static void ! 189: use_token( toknode* T ) ! 190: /* ! 191: lookup TNAMEs here instead of in tlex() ! 192: maintain block level ! 193: */ ! 194: { ! 195: static TOK last_tokens[2]; // TSCOPE not reduced at this point ! 196: static Pname last_tname; // tname :: id, where id is nested class ! 197: static Pname tdef_name; // typedef tname tdef_name ! 198: ! 199: T->used = 1; ! 200: ! 201: // error('d', &T->place, "use_token: %k, lasttk: %k",T->tok,lasttk ); ! 202: // error('d', &T->place, "last_tokens: %k %k",last_tokens[two_back],last_tokens[one_back]); ! 203: // error('d', &T->place, "use_token: last_tname: %n", last_tname); ! 204: ! 205: switch ( T->tok ) { ! 206: case ID: ! 207: Pname n; ! 208: // error('d', &T->place, "use_token: %s", T->retval.s ); ! 209: if ( last_tokens[one_back] == MEM && ! 210: last_tokens[two_back] == TNAME && ! 211: (n=ktbl->look(T->retval.s,NESTED))) ! 212: { // TYPEDEF :: ID, nested class ctor ! 213: if (tdef_name && tdef_name->n_key==NESTED && ! 214: strcmp(tdef_name->string,n->string)==0) ! 215: { ! 216: T->tok = TNAME; ! 217: T->retval.pn = n; ! 218: break; ! 219: } ! 220: else { // TNAME :: ID, where ID may be nested class ! 221: for ( Pname nn = n; nn; nn = nn->n_tbl_list ) ! 222: { ! 223: TOK sw; ! 224: if ( nn->n_key != NESTED ) continue; ! 225: Ptype tt = return_nstd_local_type(nn,sw); ! 226: Pclass cl = tt->in_class; ! 227: if (strcmp(last_tname->string,cl->string)==0) ! 228: { ! 229: T->tok = TNAME; ! 230: T->retval.pn = nn; ! 231: break; ! 232: } ! 233: } ! 234: } ! 235: } ! 236: else ! 237: if ( bl_level && ! 238: // TNAME:: and :: cannot refer to ``local'' TNAME ! 239: last_tokens[one_back] != MEM && ! 240: (n=ktbl->look(T->retval.s,LOCAL)) ) ! 241: { ! 242: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) ); ! 243: T->tok = TNAME; ! 244: T->retval.pn = n; ! 245: } ! 246: else if ( n=ktbl->look(T->retval.s,0) ) { ! 247: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: global class instance: %n", n ) ); ! 248: // error( 'd', &T->place, "use_token: global class instance: %n %t", n, n->tp ); ! 249: ! 250: // X:: ?, then n cannot be a global TNAME ! 251: // except in the case of a constructor ! 252: if (last_tokens[one_back] == MEM && ! 253: last_tokens[two_back] == TNAME && ! 254: strcmp(T->retval.s,last_tname->string)) ! 255: ; // do nothing; i.e., return ID ! 256: else ! 257: if ( bl_level && n->tp->base != COBJ && ! 258: last_tokens[one_back] == MEM && ! 259: last_tokens[two_back] != TNAME && ! 260: gtbl->look(T->retval.s,0)) ! 261: ; // do nothing: local typedefs & enums not implemented ! 262: else { ! 263: Pname nn = 0; ! 264: TOK ntd; ! 265: if (bl_level && (nn=ktbl->look(T->retval.s,NESTED))) ! 266: { ! 267: (void) return_nstd_local_type(n,ntd); ! 268: nn = local_nested_kludge(nn,ntd==NESTED?n:0); ! 269: } ! 270: T->tok = TNAME; ! 271: T->retval.pn = nn?nn:n; ! 272: } ! 273: } ! 274: #ifdef DBG ! 275: else if(Ldebug>=1) ! 276: error('d',&T->place,"use_token: id %s",T->retval.s); ! 277: #endif ! 278: break; ! 279: case LC: ++bl_level; break; ! 280: case RC: --bl_level; break; ! 281: } ! 282: ! 283: if (T->tok != COMPL || last_tokens[one_back] != MEM) { ! 284: last_tokens[two_back] = last_tokens[one_back]; ! 285: last_tokens[one_back] = T->tok; ! 286: if (T->tok == TNAME) last_tname = T->retval.pn; ! 287: if ( last_tname && ! 288: last_tname->tp->base == TYPE ) ! 289: { ! 290: tdef_name = last_tname; ! 291: do ! 292: tdef_name = Pbase(tdef_name->tp)->b_name; ! 293: while ( tdef_name->tp->base == TYPE ); ! 294: } ! 295: } ! 296: } ! 297: ! 298: void ! 299: addtok(TOK t, YYSTYPE r, loc tloc) ! 300: { ! 301: toknode* T = new toknode(t,r,tloc); ! 302: if (front == 0) ! 303: front = rear = T; ! 304: else { ! 305: rear->next = T; ! 306: T->last = rear; ! 307: rear = T; ! 308: } ! 309: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:""); ! 310: //showQ("addtok"); ! 311: } ! 312: ! 313: extern TOK ! 314: deltok( int noset = 0 ) ! 315: { ! 316: register toknode* T = front; ! 317: USE_TOKEN(T,"deltok"); ! 318: register TOK tk = T->tok; ! 319: if ( !noset ) { yylval = T->retval; curloc = T->place; } ! 320: curr_file = curloc.file; ! 321: if (front = front->next) ! 322: front->last = 0; ! 323: else ! 324: latok = rear = 0; ! 325: delete T; ! 326: return tk; ! 327: } ! 328: ! 329: static void ! 330: add_tokens() ! 331: /* ! 332: extend lookahead token queue when depleted ! 333: */ ! 334: { ! 335: TOK tk = tlex(); ! 336: if ( tk != ID ) ! 337: return; ! 338: ! 339: while (tk == ID || tk == MEM || tk == DOT ) ! 340: tk = tlex(); ! 341: } ! 342: ! 343: extern TOK ! 344: la_look() ! 345: /* ! 346: peek at head of token queue ! 347: */ ! 348: { ! 349: LDB(1,fprintf(stderr,"\n*** la_look()")); ! 350: if ( front == 0 ) ! 351: add_tokens(); ! 352: ! 353: latok = front; ! 354: USE_TOKEN(latok,"la_look"); ! 355: LDB(1,fprintf(stderr," -- %s\n",image(latok->tok))); ! 356: return latok->tok; ! 357: } ! 358: ! 359: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar ) ! 360: void ! 361: check_decl() ! 362: /* ! 363: Lookahead to direct parsing of local/arg type declarations ! 364: la_decl() returns 1 if lookahead sees a declaration. ! 365: */ ! 366: { ! 367: TOK tk2; ! 368: switch( NEXTTOK() ) { ! 369: default: ! 370: break; ! 371: case TSCOPE: //XXX ! 372: tk2 = la_look(); ! 373: while ( tk2 == TSCOPE ) tk2 = lookahead(); ! 374: if ( tk2 == TNAME ) { ! 375: toknode* t = latok; ! 376: if(t->tok!=TNAME) ! 377: error('i',"check_decl() token scan"); ! 378: tk2 = lookahead(); ! 379: if ( tk2 == LP && la_decl() ) { ! 380: t->tok = DECL_MARKER; //TNAME ! 381: } ! 382: } ! 383: break; ! 384: case TYPE: case TNAME: ! 385: if ( la_look() == LP && la_decl() ) { ! 386: must_be_id = 0; ! 387: DECL_TYPE=yychar; ! 388: yychar = DECL_MARKER; ! 389: } ! 390: } ! 391: } ! 392: ! 393: void ! 394: check_cast() ! 395: /* ! 396: Lookahead to direct parsing of cast ! 397: la_cast() returns 1 if lookahead sees an ambiguous old-style C cast. ! 398: */ ! 399: { ! 400: TOK tk2; ! 401: switch( NEXTTOK() ) { ! 402: case TSCOPE: //XXX ! 403: tk2 = la_look(); ! 404: while ( tk2 == TSCOPE ) tk2 = lookahead(); ! 405: if ( tk2 == TNAME ) { ! 406: toknode* t = latok; ! 407: if(t->tok!=TNAME) ! 408: error('i',"check_cast() token scan"); ! 409: tk2 = lookahead(); ! 410: if ( tk2 == LP && la_decl() ) { ! 411: t->tok = DECL_MARKER;//TNAME ! 412: } ! 413: } ! 414: break; ! 415: case TYPE: case TNAME: ! 416: if ( la_look() == LP && la_cast() ) { ! 417: must_be_id = 0; ! 418: DECL_TYPE = yychar; ! 419: yychar = DECL_MARKER; ! 420: } ! 421: } ! 422: } ! 423: ! 424: ! 425: static int ! 426: latype( TOK t ) ! 427: { ! 428: switch ( t ) { ! 429: default: // includes friend, typedef, storage classes, etc. ! 430: return 0; ! 431: case CHAR: case SHORT: case INT: case LONG: ! 432: case FLOAT: case DOUBLE: ! 433: case UNSIGNED: ! 434: return 1; ! 435: } ! 436: } ! 437: ! 438: static int ! 439: laexpr( TOK t ) ! 440: { ! 441: switch ( t ) { ! 442: default: ! 443: return 0; ! 444: case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR: ! 445: case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS: ! 446: case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP: ! 447: case SHIFTOP: case ICOP: ! 448: return 1; ! 449: } ! 450: } ! 451: ! 452: ! 453: static TOK ! 454: lookahead() ! 455: /* ! 456: advance lookahead pointer, lexing at end of Q ! 457: handle occurrences of TNAME and TSCOPE ! 458: (should be kept up to date with lalex()) ! 459: */ ! 460: { ! 461: TOK tk; ! 462: TOK tk2; ! 463: TOK prev_tk = 0; ! 464: YYSTYPE lastval; ! 465: ! 466: if ( latok == rear ) { ! 467: add_tokens(); ! 468: if ( latok ) ! 469: latok = latok->next; ! 470: else ! 471: latok = front; ! 472: } ! 473: else ! 474: latok = latok->next; ! 475: ! 476: if ( latok->last ) { ! 477: prev_tk = latok->last->tok; ! 478: lastval = latok->last->retval; ! 479: } ! 480: ! 481: nexttok: ! 482: USE_TOKEN(latok,"lookahead1"); ! 483: tk = latok->tok; ! 484: if ( tk == ID || tk == TNAME ) ! 485: { ! 486: if (latok->next == 0) add_tokens(); ! 487: USE_TOKEN(latok->next,"lookahead2"); ! 488: /* TOK */ tk2 = latok->next->tok; ! 489: if ( tk == TNAME ) { ! 490: if ( tk2 == MEM || tk2 == DOT ) { ! 491: tscope: tk = TSCOPE; ! 492: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 ); ! 493: //XXX -- should be modified to loop and do lookup ! 494: latok = latok->next; ! 495: if (latok->next == 0) add_tokens(); ! 496: USE_TOKEN(latok->next,"lookahead3"); ! 497: tk2 = latok->next->tok; ! 498: if ( tk2 == MUL ) { ! 499: tk = MEMPTR; ! 500: latok = latok->next; ! 501: } ! 502: } ! 503: else if (( prev_tk == MUL && tk2 != RP ) ! 504: || prev_tk == AND ) ! 505: { ! 506: tk = ID; ! 507: latok->retval.pn->hide(); ! 508: latok->tok = ID; ! 509: latok->retval.s = latok->retval.pn->string; ! 510: } ! 511: } ! 512: else if ( tk2 == MEM ) { ! 513: // ID :: ! 514: //XXX latok = latok->next->next; ! 515: //XXX goto nexttok; ! 516: goto tscope; // treat as tscope ! 517: } ! 518: ! 519: if ( tk == ID && ! 520: ( tk2 == ID || ! 521: ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) { ! 522: // ID ID ! 523: latok = latok->next; ! 524: goto nexttok; ! 525: } ! 526: } ! 527: ! 528: if ( tk == ID ) { ! 529: Pname nstd = ktbl->look(latok->retval.s,NESTED); ! 530: if (nstd && (must_be_id == 0 || ! 531: must_be_id && prev_tk == LP)) { ! 532: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too ! 533: Pname n = check_for_nested(nstd,prev_tk,lastval,tk2); ! 534: if ( n ) { ! 535: tk = latok->tok = TNAME; ! 536: latok->retval.pn = n; ! 537: } ! 538: } ! 539: } ! 540: ! 541: return tk; ! 542: } ! 543: ! 544: static Pname mem_sel = 0; ! 545: char *class_typedef = 0; ! 546: ! 547: static Pname ! 548: do_local_class( Pname n, int lex_level ) ! 549: { /* ! 550: * modify to ``do_local_type: ! 551: * do local types: enums and typedefs ! 552: */ ! 553: Pname nn = n; ! 554: if ( n->tp ) { // already a TNAME ! 555: Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0; ! 556: if ( n->lex_level != lex_level || (cl && cl->lcl) ) { ! 557: local_hide( n ); ! 558: nn = new name( n->string ); ! 559: nn->lex_level = lex_level>=0?lex_level:0; ! 560: } ! 561: else ! 562: if ( lex_level == n->lex_level && cl->defined ) { ! 563: error( "localC %n redefined", n ); ! 564: return n; ! 565: } ! 566: } ! 567: ! 568: nn = nn->tname( lastval.t ); ! 569: modified_tn = modified_tn->l; ! 570: nn->n_key = LOCAL; ! 571: local_class = new name_list( nn, local_class ); ! 572: local_blk = new name_list( nn, local_blk ); ! 573: ! 574: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp)); ! 575: return nn; ! 576: } ! 577: ! 578: static char* ! 579: make_nested_name( char *s, Pclass cl ) ! 580: { // Q<cnt>_<class_names><space><null> ! 581: const nested_depth = 9; ! 582: char *str_arr[nested_depth]; ! 583: int size_arr[nested_depth]; ! 584: int cnt = 2; ! 585: int size = 4; // Q,<cnt>,<_>,<null> ! 586: ! 587: str_arr[0] = s; str_arr[1] = cl->string; ! 588: ! 589: size += size_arr[0] = strlen(s); ! 590: size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string); ! 591: ! 592: for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) { ! 593: if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth); ! 594: size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string); ! 595: str_arr[cnt++] = nc->string; ! 596: } ! 597: ! 598: for ( int i=0; i<cnt; i++ ) // <nnn><string> ! 599: size += size_arr[i]>99?3:size_arr[i]<10?1:2; ! 600: ! 601: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size ); ! 602: char *result = new char[size]; ! 603: sprintf(result, "Q%d_", cnt ); ! 604: size = 3; ! 605: for ( i=cnt; i; i-- ) { ! 606: sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]); ! 607: size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2); ! 608: } ! 609: ! 610: //error('d', "size: %d ", size ); ! 611: result[size] = '\0'; ! 612: //error('d', "make_nested_name result: %s", result ); ! 613: return result; ! 614: } ! 615: ! 616: int is_empty( Pclass cl, bit const_chk ) ! 617: { /* for nested class check, empty means *no* members ! 618: * for const object check, means no *data* members ! 619: */ ! 620: ! 621: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size ); ! 622: ! 623: int mbr_cnt = cl->memtbl->max(); ! 624: if ( mbr_cnt == 0 ) return 1; ! 625: ! 626: if ( cl->baselist == 0 && cl->real_size!=1 ) ! 627: return 0; ! 628: ! 629: // empty class to turn on transitional nested class scope ! 630: if ( const_chk == 0 && ! 631: ( cl->baselist != 0 || mbr_cnt > 1 )) return 0; ! 632: ! 633: int i = 1; ! 634: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) { ! 635: if (nn->base==NAME && ! 636: nn->n_union==0 && ! 637: nn->tp->base!=FCT && ! 638: nn->tp->base!=OVERLOAD && ! 639: nn->tp->base!=CLASS && ! 640: nn->tp->base!=ENUM && ! 641: nn->tp->base!=EOBJ && ! 642: nn->n_stclass != STATIC) ! 643: { ! 644: if ( nn->string[0]=='_' && ! 645: nn->string[1]=='_' && ! 646: nn->string[2]=='W' ) ! 647: return 1; ! 648: else return 0; ! 649: } ! 650: } ! 651: ! 652: return 1; // if here, no data members encountered ! 653: } ! 654: ! 655: static int ! 656: is_empty( Penum en ) ! 657: { // is this an empty enum ?? ! 658: ! 659: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators); ! 660: if ( en->no_of_enumerators != 0 ) ! 661: return 0; ! 662: ! 663: return 1; ! 664: } ! 665: ! 666: static Pname ! 667: check_nested_type( Pname nm ) ! 668: { ! 669: // error('d', "check nested type: %n ccl: %t", nm, ccl ); ! 670: ! 671: Pname nx, n = ktbl->look(nm->string, NESTED); ! 672: if ( n == 0 || n == nm ) return nm; ! 673: ! 674: int cnt = 1; ! 675: for (nx = n; n; n=n->n_tbl_list ) ! 676: if (n->n_key == NESTED) ++cnt; ! 677: ! 678: if ( cnt > 1 ) { ! 679: error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt ); ! 680: error( 'i', "cannot recover from previous errors" ); ! 681: } ! 682: else { ! 683: TOK ntk; ! 684: Ptype tt = return_nstd_local_type(nx,ntk); ! 685: error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string); ! 686: } ! 687: return nx; ! 688: } ! 689: ! 690: static int ! 691: in_local_class( Pclass cl ) ! 692: { ! 693: if ( cl->lex_level ) ! 694: return 1; ! 695: if ( cl->in_class ) ! 696: return in_local_class( cl->in_class ); ! 697: return 0; ! 698: } ! 699: ! 700: static Pname ! 701: do_nested_type( Pname n ) ! 702: { ! 703: Pname nn = n; ! 704: char *str = 0; ! 705: ! 706: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl ); ! 707: // error('d', "lasttk: %k class_typedef: %s", lasttk, class_typedef); ! 708: if ( in_typedef && ccl->string[0]=='_' ! 709: && ccl->string[1]=='_' ! 710: && ccl->string[2]=='C') return n; ! 711: ! 712: if ( n->tp ) ! 713: { // already a TNAME : ! 714: // hide existing instance, encode new instance ! 715: /* ! 716: * need handle the anomaly: ! 717: * class x; ! 718: * x *p; ! 719: * class y { ! 720: * class x{ ... }; // oops ! 721: * }; ! 722: */ ! 723: if (n->tp->base==COBJ) { ! 724: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp); ! 725: if (cl->defined == 0 && lasttk == AGGR) { ! 726: error('w',"forward declaration ofC%n resolved to nested%t::%s",n,ccl,n->string); ! 727: cl->lcl = new char[9]; ! 728: strcpy(cl->lcl,"FUDGE007"); // license to hack ! 729: n->lex_level=Pbase(n->tp)->b_name->lex_level=0; ! 730: return n; ! 731: } ! 732: } ! 733: else if (n->tp->base==EOBJ) { // watch out for enum x; ! 734: Penum en = Penum(Pbase(n->tp)->b_name->tp); ! 735: if (en->defined == 0 && lasttk == ENUM) return n; ! 736: } ! 737: ! 738: nested_hide( n ); ! 739: nn = new name( n->string ); ! 740: str = make_nested_name( n->string, ccl ); ! 741: } ! 742: else ! 743: // make sure we haven't already seen a nested instance ! 744: // if so, for transition, this needs to be an error ! 745: if (ktbl->look( n->string, NESTED )) ! 746: error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string); ! 747: if ( in_typedef && ! 748: ( class_typedef == 0 || ! 749: strcmp(nn->string,class_typedef)==0 )) ! 750: { ! 751: if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x; ! 752: error( "nested Tdef %s redefines immediately enclosing class", nn->string ); ! 753: error( 'i', "cannot recover from previous errors" ); ! 754: } ! 755: ! 756: // make sure there isn't an identifier at global scope being defined ! 757: // by a nested typedef -- previously an error; keep it so for transition ! 758: Pname tn; ! 759: if ( n->tp == 0 && in_local_class(ccl)==0 && ! 760: (tn=gtbl->look(n->string,0))) { ! 761: error( "nested Tdef %s redefines global %n", n->string, tn ); ! 762: error( 'i', "cannot recover from previous errors" ); ! 763: } ! 764: ! 765: nn->tpdef = new type; ! 766: nn->tpdef->nested_sig = str; ! 767: nn->tpdef->in_class = ccl; ! 768: nn->tpdef->lex_level = NESTED; ! 769: PERM(nn->tpdef); ! 770: } ! 771: else { ! 772: nn = nn->tname( lastval.t ); ! 773: Pname tn = Pbase(nn->tp)->b_name; ! 774: Ptype tt = tn->tp; ! 775: if ( tt->defined && tt->in_class == ccl) { ! 776: error( "nested %t redefines immediately enclosing class", nn->string ); ! 777: error( 'i', "cannot recover from previous errors" ); ! 778: } ! 779: tt->nested_sig = str; ! 780: modified_tn = modified_tn->l; ! 781: nn->lex_level = tn->lex_level = 0; ! 782: nested_type = new name_list( nn, nested_type ); ! 783: } ! 784: nn->n_key = NESTED; ! 785: return nn; ! 786: } ! 787: ! 788: static Pname dtor_seen; ! 789: static int in_expr; ! 790: extern int in_sizeof; ! 791: ! 792: extern TOK ! 793: lalex() ! 794: /* return next token to grammar */ ! 795: { ! 796: register TOK tk; ! 797: if ( front == 0 ) ! 798: add_tokens(); // extend lookahead queue ! 799: LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before")); ! 800: ! 801: gettok: ! 802: tk = deltok(); ! 803: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef); ! 804: ! 805: if ( tk == ID || tk == TNAME ) ! 806: { ! 807: TOK tk2 = la_look(); ! 808: int lex_level = bl_level - in_class_decl - (tk2 == LC ); ! 809: ! 810: if ( tk == TNAME ) ! 811: { ! 812: //error('d', "lalex tname %n; lasttk: %k tk2: %k", yylval.pn, lasttk, tk2); ! 813: //error('d', " must_be_id: %d must_be_expr %d decl_type %d",must_be_id,must_be_expr,DECL_TYPE); ! 814: //error('d', " bl_level: %d parsing_members %d",bl_level,parsing_class_members); ! 815: if ( tk2 == LP ! 816: && (bl_level == 0 || parsing_class_members) ! 817: && ( laexpr(lasttk) == 0 ) ! 818: && must_be_expr == 0 ! 819: && DECL_TYPE == 0 ) { ! 820: if (la_decl()) { ! 821: must_be_id = 0; ! 822: DECL_TYPE = tk; ! 823: tk = DECL_MARKER; ! 824: goto ret; ! 825: } ! 826: } ! 827: ! 828: // note: *** can handle local typedefs here, too! ! 829: if ( in_typedef && ! 830: in_typedef->base != 0 && ! 831: ccl && in_mem_fct == 0 && ! 832: (tk2 == SM || tk2 == RP || tk2 == LB)) ! 833: yylval.pn = do_nested_type(yylval.pn); ! 834: ! 835: if ( lasttk == AGGR || lasttk == ENUM ) { ! 836: if ( tk2 == LC || tk2 == COLON ) { // class definition ! 837: if ( in_typedef && ! 838: in_typedef->base == 0 && ! 839: class_typedef == 0 ) ! 840: class_typedef = yylval.pn->string; ! 841: if ( lex_level ! 842: && (in_class_decl==0 || in_mem_fct) ! 843: && lasttk != ENUM ) // temporary ! 844: yylval.pn = do_local_class( yylval.pn, lex_level ); ! 845: else ! 846: if ( in_class_decl && ccl ) ! 847: yylval.pn = do_nested_type( yylval.pn ); ! 848: } ! 849: } ! 850: ! 851: if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) { ! 852: if (tk2==DOT) ! 853: error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)"); ! 854: crunch: ! 855: tk = TSCOPE; ! 856: {//XXX -- should be modified to do lookup and del at each :: ! 857: while ( (tk2 = lookahead()) == TSCOPE ) ; ! 858: if ( tk2 == TNAME ) { ! 859: tk2 = lookahead(); ! 860: if ( tk2 == LP ! 861: && (bl_level == 0 || parsing_class_members) ! 862: && ( laexpr(lasttk) == 0 ) ! 863: && must_be_expr == 0 ! 864: && DECL_TYPE == 0 ) { ! 865: if (la_decl()) { ! 866: must_be_id = 0; ! 867: //DECL_TYPE = tk;//??? ! 868: DECL_TYPE = TNAME; ! 869: //front should be :: ! 870: front->tok = TSCOPE; ! 871: front->retval.pn = yylval.pn; ! 872: yylval.pn = 0; ! 873: tk = DECL_MARKER; ! 874: goto ret; ! 875: } ! 876: } ! 877: } ! 878: } ! 879: tk2 = deltok(1); ! 880: tk2 = la_look(); ! 881: if ( tk2 == MUL ) { ! 882: tk = MEMPTR; ! 883: tk2 = deltok(1); ! 884: } ! 885: } ! 886: // Have a TNAME. Check to be sure. ! 887: else if ( must_be_id ){ ! 888: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2); ! 889: if ( in_class_decl ! 890: && lasttk == TYPE ! 891: && tk2 == LP ! 892: && strcmp(yylval.pn->string,ccl->string) == 0 ) ! 893: error("%nK with returnT", yylval.pn); ! 894: ! 895: else if ( lasttk == TYPE && lastval.t == OVERLOAD ! 896: && ( tk2 == SM || tk2 == LP ) ) ! 897: { ! 898: tk = ID; ! 899: yylval.pn->hide(); ! 900: yylval.pn = new name( yylval.pn->string ); ! 901: yylval.pn->n_oper = TNAME; ! 902: } ! 903: else if ( lasttk == OPERATOR || ! 904: in_typedef && yylval.pn->n_key == NESTED) ! 905: must_be_id = 0; ! 906: else if ( lasttk != TSCOPE // watch out for X::X ! 907: || lastval.pn != yylval.pn ! 908: || (in_typedef && ! 909: in_typedef->check( yylval.pn->tp,0) == 0 )) ! 910: { ! 911: tk = ID; ! 912: if ( in_typedef && (lasttk == MUL || lasttk == REF)) { ! 913: defer_check = 1; ! 914: in_tag = yylval.pn; ! 915: } ! 916: ! 917: if ( lasttk == MEM && yylval.pn->lex_level ) { ! 918: Pname nn = gtbl->look( yylval.pn->string, 0 ); ! 919: if (nn == 0 ) ! 920: error( "%k%s undeclared", lasttk, yylval.pn->string); ! 921: else ! 922: yylval.pn = nn; ! 923: } ! 924: else { ! 925: // error('d',"lalex: else: lasttk: %k", lasttk ); ! 926: if (lasttk!=DOT && lasttk!=REF ! 927: && lasttk!=TSCOPE && lasttk != GOTO ! 928: // handle typedefs in basetype::check ! 929: // when type is available ! 930: && !in_typedef) { ! 931: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn); ! 932: yylval.pn->hide(); ! 933: } ! 934: ! 935: yylval.pn = new name (yylval.pn->string); ! 936: if (lasttk!=DOT && lasttk!=REF && ! 937: lasttk!=TSCOPE && lasttk !=GOTO) ! 938: yylval.pn->n_oper = TNAME; ! 939: } ! 940: if ( defer_check ) defer_check = 0; ! 941: } ! 942: } // must_be_id ! 943: ! 944: if ( in_class_decl && ! 945: ccl->lex_level && ! 946: yylval.pn->lex_level != 0 && ! 947: yylval.pn->tp && ! 948: (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ)) ! 949: { ! 950: Pname n = gtbl->look( yylval.pn->string,0); ! 951: if ( in_mem_fct ) { ! 952: if (n && n->base == TNAME ) { ! 953: error('w', "local typedef %n(%t) is not in scope of local class %s members; using global (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp ); ! 954: yylval.pn = n; ! 955: } else ! 956: error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string); ! 957: } ! 958: } ! 959: ! 960: // if we still have a TNAME, make sure have the right TNAME ! 961: // possibility of ananchronistic reference to nested type ! 962: Ptype nbt = yylval.pn->tp; ! 963: if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y; ! 964: (nbt->base == EOBJ || nbt->base == COBJ)) ! 965: { ! 966: Ptype t = Pbase(nbt)->b_name->tp; ! 967: if ( ccl && t->in_class && ! 968: strcmp(t->in_class->string, ccl->string)) ! 969: { ! 970: switch( nbt->base ) { ! 971: case COBJ: ! 972: if (is_empty(Pclass(t))) ! 973: yylval.pn = check_nested_type( yylval.pn ); ! 974: break; ! 975: case EOBJ: ! 976: if (is_empty(Penum(t))) ! 977: yylval.pn = check_nested_type( yylval.pn ); ! 978: break; ! 979: }; ! 980: } ! 981: } ! 982: } ! 983: else ! 984: { // tk == ID ! 985: char *s = yylval.s; ! 986: Pname n = ktbl->look( s, HIDDEN ); ! 987: Pname nstd = ktbl->look( s, NESTED ); ! 988: ! 989: // inside a class definition, ccl, that is nested ! 990: // s is a nested class name, and is the name of ccl ! 991: if (ccl && ccl->in_class && nstd && ! 992: strcmp(s, ccl->string)==0) ! 993: { ! 994: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 995: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ) ! 996: ? Pbase(nn->tp)->b_name->tp : nn->tpdef; ! 997: Pclass cl = tt->in_class; ! 998: if ( nn->n_key != NESTED ) continue; ! 999: if (strcmp(ccl->in_class->string,cl->string) == 0) { ! 1000: tk = TNAME; ! 1001: yylval.pn = nn; ! 1002: n = nstd = nn; ! 1003: } ! 1004: } ! 1005: } ! 1006: ! 1007: if (tk2 == MEM) { ! 1008: // ID :: ! 1009: if (n) { ! 1010: yylval.pn = n; ! 1011: /*XXX*/ goto crunch; ! 1012: } ! 1013: else ! 1014: if (nstd && ! 1015: nstd->n_tbl_list==0) ! 1016: { ! 1017: yylval.pn = nstd; ! 1018: tk = TSCOPE; ! 1019: tk2 = deltok(1); ! 1020: tk2 = la_look(); ! 1021: if (tk2 == MUL ) { ! 1022: tk = MEMPTR; ! 1023: tk2 = deltok(1); ! 1024: } ! 1025: } ! 1026: else { ! 1027: error( "%s:: %sis not aTN", s, s ); ! 1028: tk2 = deltok(1); ! 1029: goto gettok; ! 1030: } ! 1031: } ! 1032: else // transitional kludge ! 1033: if ( n && nstd && n == nstd ) ! 1034: ; // null statement ! 1035: ! 1036: // Have an ID. Check last token to be sure. ! 1037: else if (lasttk==ENUM || lasttk==AGGR) { ! 1038: int fd = tk2!=LC && tk2!=COLON; ! 1039: if ( in_typedef && fd == 0 && ! 1040: in_typedef->base == 0 && ! 1041: class_typedef == 0 ) ! 1042: class_typedef = yylval.s; ! 1043: tk = TNAME; ! 1044: if ( nstd ) { ! 1045: // in transitional model, need flag this as error ! 1046: if ( fd == 0 ) { // real definition ! 1047: if ( ccl == 0 ) ! 1048: error("nested and global%k %s(to do this place global%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s); ! 1049: else ! 1050: error("multiple nested%k %s(to do this place global%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s); ! 1051: error( 'i', "cannot recover from previous errors" ); ! 1052: } ! 1053: } ! 1054: else ! 1055: if (n==0) { // new tag, define it ! 1056: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl); ! 1057: n = new name( s ); ! 1058: if ( fd ) // struct X*, etc. ! 1059: n->lex_level=0; ! 1060: else ! 1061: n->lex_level=lex_level>=0?lex_level:0; ! 1062: ! 1063: if ( ccl && fd == 0 && ! 1064: in_class_decl && ! 1065: in_mem_fct == 0 ) ! 1066: n = do_nested_type( n ); ! 1067: else ! 1068: // note: ***** modify to handle local typedef ! 1069: // note: ***** add local enums ! 1070: if ( n->lex_level && ! 1071: lasttk != ENUM ) // temporary ! 1072: n = do_local_class( n, n->lex_level ); ! 1073: else { ! 1074: n = n->tname( lastval.t ); ! 1075: modified_tn = modified_tn->l; ! 1076: if (fd && gtbl->look(n->string,0)) statStat = n; ! 1077: } ! 1078: } ! 1079: else { ! 1080: if (n->tp->base!=COBJ && n->tp->base!=EOBJ) { ! 1081: error( 'i', "hidden%n:%t",n,n->tp ); ! 1082: goto gettok; ! 1083: } ! 1084: ! 1085: if ( tk2 == LC || tk2 == COLON ) { ! 1086: // class declared and hidden but not yet defined ! 1087: // may have ctor defined which invalidates hiding ! 1088: statStat = n; ! 1089: n->n_key = 0; // inside class definition it cannot be hidden ! 1090: } ! 1091: } ! 1092: yylval.pn = nstd?nstd:n; ! 1093: } ! 1094: else { ! 1095: tk = ID; ! 1096: yylval.pn = new name( s ); ! 1097: } ! 1098: ! 1099: if ( tk == ID ) ! 1100: { ! 1101: switch ( tk2 ) { ! 1102: case ID: case TNAME: case AGGR: case ENUM: ! 1103: { ! 1104: Pname n = 0; ! 1105: ! 1106: if ((curr_scope||ccl) && nstd) { ! 1107: // within class scope in which nested class is visible ! 1108: // curr_scope == set by TSCOPE, X::foo() { ... } ! 1109: // ccl == parsing class definition ``ccl'' ! 1110: ! 1111: char *str = curr_scope?curr_scope->string:ccl->string; ! 1112: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 1113: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ) ! 1114: ? Pbase(nn->tp)->b_name->tp : nn->tpdef; ! 1115: Pclass cl = tt->in_class; ! 1116: if ( nn->n_key != NESTED ) continue; ! 1117: if ( strcmp(str,cl->string) == 0){ ! 1118: tk = TNAME; ! 1119: yylval.pn = nn; ! 1120: if (lasttk == TYPE && ! 1121: lastval.t == TYPEDEF ) ! 1122: in_typedef = yylval.pn->tp; ! 1123: break; ! 1124: } ! 1125: } ! 1126: } ! 1127: if (tk == TNAME) break; // found nested class ! 1128: ! 1129: n = ktbl->look( s, HIDDEN ); ! 1130: if ( n ) { ! 1131: Pname nn = n; ! 1132: switch ( n->tp->base ) { ! 1133: default: ! 1134: error("typedef %sis not visible in this scope", s ); ! 1135: break; ! 1136: case COBJ: ! 1137: if (is_empty(Pclass(Pbase(n->tp)->b_name->tp))) ! 1138: n = check_nested_type( nn ); ! 1139: if (nn == n) ! 1140: error("%sis hidden: use struct %s%s", s,s,front->retval.s); ! 1141: break; ! 1142: case EOBJ: ! 1143: if (is_empty(Penum(Pbase(n->tp)->b_name->tp))) ! 1144: n = check_nested_type( nn ); ! 1145: if (nn == n) ! 1146: error("%sis hidden: use enum %s%s", s,s,front->retval.s); ! 1147: break; ! 1148: }; ! 1149: tk = TNAME; ! 1150: yylval.pn = n; ! 1151: } ! 1152: else ! 1153: if (n=ktbl->look(s,NESTED)) ! 1154: { ! 1155: TOK ntk; ! 1156: bit ok = 0; ! 1157: Ptype tt = return_nstd_local_type(n,ntk); ! 1158: Pclass cl = tt->in_class; ! 1159: if (ccl) { ! 1160: // x::y unncessary with in_class, ! 1161: // a derived class of in_class ! 1162: // or classes enclosing in_class ! 1163: if (ccl==cl || ccl->has_base(cl)) ! 1164: ok++; ! 1165: else { ! 1166: for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class) ! 1167: if ( eccl == cl ) { ok++; break; } ! 1168: } ! 1169: } ! 1170: if (!ok) ! 1171: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string ); ! 1172: tk = TNAME; ! 1173: yylval.pn = n; ! 1174: } ! 1175: else { // probably a typo ! 1176: if ( tk2 == ID ) ! 1177: error("%s%s: %sis not aTN", s,front->retval.s,s); ! 1178: else if ( tk2 == TNAME ) ! 1179: error("%s%s: %sis not aTN", s,front->retval.pn->string,s); ! 1180: else ! 1181: error("%s%k: %sis not aTN", s,front->retval.t,s); ! 1182: goto gettok; ! 1183: } ! 1184: break; ! 1185: } ! 1186: case DOT: case REF: ! 1187: mem_sel = yylval.pn; ! 1188: break; ! 1189: default: ! 1190: if ( lasttk == TNAME && tk2 == LC ) ! 1191: { ! 1192: error("T%s %k: %s is unexpected", s, tk2, s ); ! 1193: goto gettok; ! 1194: } ! 1195: ! 1196: // have an ID. lets just make sure it should not be a TNAME ! 1197: if (curr_scope||ccl||nstd) { ! 1198: if (ccl && in_typedef && ! 1199: in_typedef->base != 0 && ! 1200: in_mem_fct == 0 && ! 1201: (tk2 == SM || tk2 == RP || tk2 == LB)) ! 1202: { ! 1203: yylval.pn = do_nested_type( yylval.pn ); ! 1204: tk = TNAME; ! 1205: } ! 1206: else ! 1207: if (nstd && must_be_id == 0 && in_expr == 0) { ! 1208: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk); ! 1209: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level); ! 1210: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0); ! 1211: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 1212: TOK ntk; ! 1213: bit ok = 0; ! 1214: Ptype tt = return_nstd_local_type(nn,ntk); ! 1215: Pclass cl = tt->in_class; ! 1216: // error('d',"xcl: %t ccl: %t", xcl, ccl ); ! 1217: if ( xcl ) { ! 1218: if (xcl==cl || xcl->has_base(cl) || ccl == cl) ! 1219: ok++; ! 1220: else { ! 1221: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class) ! 1222: if ( eccl == cl ) { ok++; break; } ! 1223: } ! 1224: } ! 1225: ! 1226: if (nn == nstd) ! 1227: { ! 1228: if ( ! 1229: // special case: foo(X, ! 1230: // in_arg_list not set until **after** X is handled ! 1231: ((in_arg_list || lasttk==LP) && // foo(nestedX ! 1232: (tk2==CM || tk2==ASSIGN || ! 1233: (tk2==RP && lasttk!=MUL && lasttk!=REF))) ! 1234: || // class x : public nestedX ! 1235: (tk2==LC && (lasttk==PR || lasttk==VIRTUAL)) ! 1236: || // nestedX [*&] ! 1237: (tk2 == MUL || tk2==AND) ! 1238: || (lasttk==LP && tk2==RP) ! 1239: || (lasttk==TSCOPE && lastval.pn == nn) ! 1240: || (lasttk==COMPL && dtor_seen == nn) ! 1241: || (lasttk==TYPE && lastval.t == TYPEDEF) ! 1242: || lasttk == OPERATOR ! 1243: || lasttk == NEW || in_sizeof ) ! 1244: { // must be type name, and it must be nested: ! 1245: if ( nstd->n_tbl_list == 0 ) { // only one: ok ! 1246: if (lasttk != TSCOPE && !ok ) ! 1247: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string); ! 1248: break; ! 1249: } ! 1250: else { ! 1251: if (lasttk != TSCOPE && !ok){ ! 1252: error("ambiguous nested type %s, use X::%s",nn->string,nn->string); ! 1253: error( 'i', "cannot recover from previous errors" ); ! 1254: } ! 1255: } ! 1256: } ! 1257: ! 1258: } ! 1259: if ( nn->n_key != NESTED ) continue; ! 1260: if (xcl && ! 1261: strcmp(xcl->string,cl->string) == 0) break; ! 1262: } // end: for nn = nstd ! 1263: ! 1264: if (nn) { ! 1265: tk = TNAME; ! 1266: yylval.pn = nn; ! 1267: if (lasttk == TYPE && ! 1268: lastval.t == TYPEDEF ) ! 1269: in_typedef = yylval.pn->tp; ! 1270: } ! 1271: } // end: if (nstd) ! 1272: } // end: if (curr_scope||ccl) ! 1273: break; ! 1274: } // end: switch tk2 ! 1275: } // end: if (tk == ID) ! 1276: } ! 1277: ! 1278: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk ); ! 1279: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk ); ! 1280: if (lex_level && tk==ID && tk2==LP && ! 1281: (lasttk==LC || lasttk==RC || lasttk==RP || ! 1282: lasttk == ASSIGN || lasttk == SM)) ! 1283: in_expr = 1; ! 1284: else in_expr = 0; ! 1285: ! 1286: } ! 1287: if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) ) ! 1288: // XXX || tk == TSCOPE || tk == MEM ! 1289: || tk == REF || tk == DOT || tk == GOTO ! 1290: || tk == MEMPTR ) ! 1291: // TNAME cannot immediately follow a type name, ! 1292: // scope operator, right curly, selection, or goto ! 1293: must_be_id = 1; ! 1294: else ! 1295: must_be_id = 0; ! 1296: ! 1297: switch ( tk ) { ! 1298: case SM: ! 1299: mem_sel = 0; // no break ! 1300: in_expr = 0; ! 1301: case RP: case RC: must_be_expr = 0; break; ! 1302: case COLON: ! 1303: if (lasttk == RP || ! 1304: (lasttk == TYPE && lastval.t == CONST)) ! 1305: must_be_expr = 1; ! 1306: break; ! 1307: case SIZEOF: ! 1308: in_sizeof = 1; ! 1309: break; ! 1310: }; ! 1311: ret: ! 1312: if ( tk == COMPL && lasttk == TSCOPE ) ! 1313: dtor_seen = lastval.pn; ! 1314: else dtor_seen = 0; ! 1315: lasttk = tk; ! 1316: lastval = yylval; ! 1317: LDB(1,showQ("after"); ! 1318: fprintf(stderr,"returning '%s'",image(tk)); ! 1319: if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string); ! 1320: fprintf(stderr,"\n"); ! 1321: ); ! 1322: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen ); ! 1323: return tk; ! 1324: } ! 1325: ! 1326: extern void ! 1327: la_backup( TOK t, YYSTYPE r ) ! 1328: /* ! 1329: called by parser to push token back on front of queue ! 1330: */ ! 1331: { ! 1332: LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t))); ! 1333: if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); } ! 1334: register toknode* T = new toknode(t,r,curloc); ! 1335: if (front) { ! 1336: front->last = T; ! 1337: T->next = front; ! 1338: T->last = 0; ! 1339: front = T; ! 1340: } else ! 1341: front = rear = T; ! 1342: lasttk = 0; ! 1343: } ! 1344: ! 1345: extern int ! 1346: la_sctype( TOK t ) ! 1347: { ! 1348: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok); ! 1349: if ( t != latok->tok && t != TSCOPE && t != MEMPTR ) ! 1350: error( 'i', &latok->place, "la_sctype, lalex.c" ); ! 1351: ! 1352: switch( latok->retval.t ) { ! 1353: case TYPEDEF: ! 1354: case EXTERN: ! 1355: case STATIC: ! 1356: case AUTO: ! 1357: case REGISTER: ! 1358: case OVERLOAD: ! 1359: case INLINE: ! 1360: case FRIEND: ! 1361: case CONST: ! 1362: case VOLATILE: ! 1363: return 1; ! 1364: default: ! 1365: return 0; ! 1366: } ! 1367: } ! 1368: ! 1369: extern int ! 1370: la_cast() ! 1371: /* ! 1372: called in reduction of term_lp to check for ambiguous prefix-style cast ! 1373: if result is 1, caller inserts DECL_MARKER to force reduction of cast ! 1374: */ ! 1375: { ! 1376: // yychar already designates TYPE or TNAME ! 1377: // LP must start the lookahead queue! ! 1378: LDB(1,fprintf(stderr,"\n*** la_cast()\n");); ! 1379: int tk, tk2 = latok->tok; ! 1380: ! 1381: for ( ; ; ) { ! 1382: tk = tk2; ! 1383: tk2 = lookahead(); ! 1384: ! 1385: switch( tk ) { ! 1386: case LP: ! 1387: if ( tk2 == MUL || tk2 == AND || ! 1388: tk2 == TSCOPE || tk2 == MEMPTR ) ! 1389: // T ( * ... ! 1390: // T ( C ::* ... ! 1391: continue; ! 1392: else ! 1393: // T ( exp ) ! 1394: return 0; ! 1395: case MUL: case AND: ! 1396: //if ( tk2 == SCTYPE ) ! 1397: if ( la_sctype( tk2 ) ) ! 1398: // T ( * const ... ! 1399: // T ( * volatile ... ! 1400: tk2 = lookahead(); ! 1401: continue; ! 1402: case TSCOPE: ! 1403: if ( tk2 == MUL ) ! 1404: // T ( C :: * ... ! 1405: continue; ! 1406: else ! 1407: // T ( exp ) ! 1408: return 0; ! 1409: case RP: case LB: ! 1410: // T (*)() ! 1411: // T (*[])() ! 1412: return 1; ! 1413: case MEMPTR: ! 1414: if ( tk2 == RP ) ! 1415: continue; ! 1416: } ! 1417: ! 1418: return 0; ! 1419: } ! 1420: } ! 1421: ! 1422: static int ! 1423: la_decl() ! 1424: /* ! 1425: handles ambiguities ! 1426: type (*x) () ! 1427: type (*x) [] ! 1428: at start of arg list / statement ! 1429: return val == 1 if lookahead finds a declaration ! 1430: (used for error messages only) ! 1431: if declaration is "ambiguous" (i.e., can't be recognized with ! 1432: 1-symbol lookahead), insert DECL_MARKER to force reduction ! 1433: of "type" ! 1434: */ ! 1435: { ! 1436: ! 1437: // LP must start the lookahead queue! ! 1438: LDB(1,fprintf(stderr,"\n*** la_decl()\n");); ! 1439: int tk, tk2 = latok->tok; ! 1440: int paren = 0; ! 1441: int ptr = 0; ! 1442: ! 1443: for ( ; ; ) { ! 1444: ! 1445: tk = tk2; ! 1446: tk2 = lookahead(); ! 1447: ! 1448: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 1449: switch( tk ) { ! 1450: case LP: ! 1451: if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) { ! 1452: // T ( * ... ! 1453: ++paren; ! 1454: ptr = 1; ! 1455: continue; ! 1456: } else ! 1457: if ( tk2 == MEMPTR ) { ! 1458: // T ( C ::* ... ! 1459: return 1; ! 1460: } else ! 1461: // possible redundant parens ! 1462: if ( tk2 == ID && lookahead() == RP ) { ! 1463: TOK tp = lookahead(); ! 1464: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 ); ! 1465: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl ); ! 1466: if ( tp == SM || tp == CM || tp == ASSIGN ) ! 1467: { ! 1468: // member initialization list ! 1469: if ( tp != SM && in_arg_list == 0 ) return 1; ! 1470: } ! 1471: else ! 1472: if ( tp == RP && (bl_level-in_class_decl==0)) ! 1473: return 1; ! 1474: if ( tp != LP ) ! 1475: return 0; ! 1476: latok=latok->last; // restore lookahead ! 1477: ++paren; ! 1478: continue; ! 1479: } ! 1480: else ! 1481: // T ( exp ) ! 1482: return 0; ! 1483: case MUL: case AND: ! 1484: //if ( tk2 == SCTYPE ) ! 1485: if ( la_sctype( tk2 )) ! 1486: // T ( * const ... ! 1487: // T ( * volatile ... ! 1488: return 1; ! 1489: else { ! 1490: ptr = 0; ! 1491: continue; ! 1492: } ! 1493: case MEMPTR: ! 1494: // T ( C :: * ... ! 1495: return 1; ! 1496: case TSCOPE: ! 1497: if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!! ! 1498: // T ( C :: * ... ! 1499: return 1; ! 1500: else if ( ptr ) ! 1501: // T ( exp ) ! 1502: return 0; ! 1503: else if ( tk2 == ID || tk2 == OPERATOR ) ! 1504: // T ( * C :: id ... ! 1505: continue; ! 1506: else ! 1507: // error ! 1508: return 0; ! 1509: } ! 1510: ! 1511: break; ! 1512: } ! 1513: ! 1514: if ( tk == RP || tk == LB ) ! 1515: // T (*)() ! 1516: // T (*[])() ! 1517: return 1; ! 1518: ! 1519: if ( tk != ID && tk != OPERATOR ) ! 1520: // T ( exp ) ! 1521: return 0; ! 1522: ! 1523: if ( tk == OPERATOR ) ! 1524: switch ( tk2 ) { ! 1525: case PLUS: case MINUS: case MUL: case REFMUL: ! 1526: case AND: case OR: case ER: case SHIFTOP: case EQUOP: ! 1527: case DIVOP: case RELOP: case ANDAND: case OROR: ! 1528: case NOT: case COMPL: case ICOP: case ASSIGN: ! 1529: case ASOP: case NEW: case GNEW: case DELETE: ! 1530: // OPERATOR oper ! 1531: tk2 = lookahead(); ! 1532: break; ! 1533: case LP: ! 1534: // OPERATOR () ! 1535: tk2 = lookahead(); ! 1536: if ( tk2 == RP ) { ! 1537: tk2 = lookahead(); ! 1538: break; ! 1539: } else ! 1540: return 0; ! 1541: case LB: ! 1542: // OPERATOR [] ! 1543: tk2 = lookahead(); ! 1544: if ( tk2 == LB ) { ! 1545: tk2 = lookahead(); ! 1546: break; ! 1547: } else ! 1548: return 0; ! 1549: default: // illegal operator ! 1550: return 0; ! 1551: } ! 1552: ! 1553: int allow_lp = 1; ! 1554: int allow_rp = 1; ! 1555: for ( ; ; ) { ! 1556: tk = tk2; ! 1557: tk2 = lookahead(); ! 1558: ! 1559: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 1560: switch( tk ) { ! 1561: case LP: ! 1562: if ( !allow_lp ) ! 1563: // T ( * id [ exp ] ( ... ! 1564: return 0; ! 1565: ! 1566: // Current lookahead will be a decl if ! 1567: // the next lookahead is an arg decl ! 1568: if ( tk2 == RP || tk2 == ENUM || tk2==AGGR ! 1569: || tk2==ELLIPSIS || la_sctype( tk2 )) ! 1570: // T ( * id () ! 1571: // T ( * id ) () ! 1572: return 1; ! 1573: ! 1574: if ( tk2 == TYPE || tk2 == TNAME ) { ! 1575: // T ( * id ) ( T2 ... ! 1576: if ( lookahead() == LP && !la_decl() ) ! 1577: return 0; ! 1578: return 1; ! 1579: } ! 1580: ! 1581: return 0; ! 1582: case LB: ! 1583: if ( tk2 == RB || lookahead() == RB ) ! 1584: // T ( * id [] ... ! 1585: return 1; ! 1586: else { ! 1587: // T ( * id [ exp ] ... ! 1588: allow_lp = 0; ! 1589: allow_rp = 1; ! 1590: while ( lookahead() != RB ); ! 1591: tk2 = lookahead(); ! 1592: continue; ! 1593: } ! 1594: case RP: ! 1595: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren ); ! 1596: if ( !allow_rp || !paren ) ! 1597: // T ( * id ) ) ! 1598: return 0; ! 1599: // permit redundant parentheses ! 1600: else ! 1601: if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN ) ! 1602: return 1; ! 1603: else ! 1604: if ( tk2 == RP && (bl_level-in_class_decl == 0)) ! 1605: return 1; ! 1606: else ! 1607: { ! 1608: // T ( * id ) ... ! 1609: allow_lp = 1; ! 1610: allow_rp = 0; ! 1611: --paren; ! 1612: continue; ! 1613: } ! 1614: default: ! 1615: return 0; ! 1616: } ! 1617: } ! 1618: } ! 1619: ! 1620: ! 1621: ! 1622: /* ! 1623: ** PROCESSING OF INLINE MEMBER FUNCTIONS ! 1624: */ ! 1625: static int la_snarf(); ! 1626: ! 1627: extern toknode* ! 1628: save_text() ! 1629: /* ! 1630: save text of inline def on q of class ! 1631: */ ! 1632: { ! 1633: // Q should contain at least the tokens < FDEF, X ... > ! 1634: // where X is either LC or COLON (start of ftn) ! 1635: LDB(2,fprintf(stderr,"save_text()")); ! 1636: LDB(3,fprintf(stderr,"front: %s",image(front->tok))); ! 1637: LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok))); ! 1638: latok = front->next; ! 1639: if ( la_snarf() ) { ! 1640: // append this set of tokens to ! 1641: // inline tokenq for class ! 1642: toknode* t = front; // FDEF ! 1643: if ( ccl->c_funqf == 0 ) ! 1644: ccl->c_funqf = front; ! 1645: else { ! 1646: ccl->c_funqr->next = front; ! 1647: front->last = ccl->c_funqr; ! 1648: } ! 1649: ccl->c_funqr = latok; ! 1650: front = latok->next; ! 1651: latok->next = 0; ! 1652: if (front) front->last = 0; ! 1653: return t; ! 1654: } ! 1655: return 0; ! 1656: } ! 1657: ! 1658: ! 1659: extern void ! 1660: restore_text() ! 1661: /* ! 1662: restore tokens for member inlines onto token q ! 1663: */ ! 1664: { ! 1665: LDB(2,fprintf(stderr,"restore_text()")); ! 1666: if (ccl->c_funqf == 0) // no inlines on Q ! 1667: return; ! 1668: LDB(3,fprintf(stderr," Q present: %d,%d",ccl->c_funqf,ccl->c_funqr)); ! 1669: LDB(3,fprintf(stderr," front==%s",image(ccl->c_funqf->tok))); ! 1670: LDB(3,fprintf(stderr," rear ==%s",image(ccl->c_funqr->tok))); ! 1671: ccl->c_funqr->next = front; ! 1672: if (front) front->last = ccl->c_funqr; ! 1673: front = ccl->c_funqf; ! 1674: ccl->c_funqf = ccl->c_funqr = 0; ! 1675: } ! 1676: ! 1677: ! 1678: static void ! 1679: del_tokens( toknode* marker ) ! 1680: /* ! 1681: delete tokens from marker to latok, not inclusive ! 1682: */ ! 1683: { ! 1684: if ( marker == 0 || marker == latok || marker->next == 0 ) ! 1685: error('i', "bad token queue"); ! 1686: ! 1687: LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok))); ! 1688: ! 1689: register toknode* tt = marker->next; ! 1690: if ( tt == latok ) return; ! 1691: marker->next = latok; ! 1692: latok->last->next = 0; ! 1693: latok->last = marker; ! 1694: register toknode* tx = tt; ! 1695: do { ! 1696: LDB(3,fprintf(stderr," deleting %s\n",image(tt->tok))); ! 1697: tx = tx->next; ! 1698: delete tt; ! 1699: tt = tx; ! 1700: } while ( tx ); ! 1701: } ! 1702: ! 1703: ! 1704: static int ! 1705: la_snarf() ! 1706: /* ! 1707: scan function def without processing declarations ! 1708: */ ! 1709: { ! 1710: LDB(2,fprintf(stderr,"la_snarf()")); ! 1711: loc *L = &latok->place; ! 1712: //DBPLACE(1,L.l,L.f); ! 1713: int parens = 0; ! 1714: int paren_error = 0; ! 1715: toknode* marker = latok; ! 1716: switch ( latok->tok ) { ! 1717: default: ! 1718: error('i', L, "bad token Q snarfing function: %d", latok->tok); ! 1719: case COLON: ! 1720: break; ! 1721: case LC: ! 1722: --bl_level; ! 1723: goto eatf; ! 1724: } ! 1725: LDB(2,fprintf(stderr,"\"eat\" member initializers")); ! 1726: for (;;) { ! 1727: if (latok->next == 0) add_tokens(); ! 1728: switch ( (latok=latok->next)->tok ) { ! 1729: case LP: ! 1730: ++parens; ! 1731: default: ! 1732: LDB(3,fprintf(stderr,"...%s",image(latok->tok))); ! 1733: continue; ! 1734: case RP: ! 1735: if ( (--parens < 0) && (paren_error++ == 0) ) ! 1736: error(0,&latok->place,"unbalanced ()"); ! 1737: continue; ! 1738: case LC: ! 1739: case RC: ! 1740: if ( parens <= 0 ) ! 1741: goto eatf; ! 1742: continue; ! 1743: case SM: ! 1744: if ( parens <= 0 ) { ! 1745: error(0, L, "illegal bit field"); ! 1746: del_tokens( front ); ! 1747: delete front; ! 1748: front = latok; ! 1749: front->last = 0; ! 1750: return 0; ! 1751: } ! 1752: continue; ! 1753: case EOFTOK: ! 1754: error('i',&latok->place,"unexpected end of file"); ! 1755: } // switch ! 1756: } // for ! 1757: ! 1758: eatf: ! 1759: int level = 1; ! 1760: for (;;) { ! 1761: if (latok->next == 0) add_tokens(); ! 1762: switch ( (latok=latok->next)->tok ) { ! 1763: case LC: ! 1764: ++level; ! 1765: default: ! 1766: LDB(3,fprintf(stderr,"...%s",image(latok->tok))); ! 1767: continue; ! 1768: case RC: ! 1769: LDB(3,fprintf(stderr,"...RC")); ! 1770: if (--level <= 0) { ! 1771: if (level < 0) { ! 1772: error(0,&latok->place,"unexpected '}'"); ! 1773: goto bad; ! 1774: } ! 1775: return 1; ! 1776: } ! 1777: break; ! 1778: case EOFTOK: ! 1779: error('e', &latok->place, "unbalanced {}"); ! 1780: goto bad; ! 1781: } // switch ! 1782: } // for ! 1783: bad: ! 1784: del_tokens( marker ); ! 1785: marker->tok = SM; ! 1786: return 0; ! 1787: } ! 1788: ! 1789: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2) ! 1790: { ! 1791: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk); ! 1792: TOK tk = ID; ! 1793: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0); ! 1794: ! 1795: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 1796: TOK ntk; ! 1797: bit ok = 0; ! 1798: Ptype tt = return_nstd_local_type(nn,ntk); ! 1799: Pclass cl = tt->in_class; ! 1800: if ( xcl ) { ! 1801: if (xcl==cl || xcl->has_base(cl)) ! 1802: ok++; ! 1803: else { ! 1804: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class) ! 1805: if ( eccl == cl ) { ok++; break; } ! 1806: } ! 1807: } ! 1808: ! 1809: if (nn == nstd) ! 1810: { ! 1811: if ( ((in_arg_list || lasttk==LP) && // foo(nestedX ! 1812: (tk2==CM || tk2==ASSIGN || tk2==RP)) ! 1813: || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL)) ! 1814: || (tk2 == MUL || tk2==AND) ! 1815: || (lasttk==LP && tk2==RP) ! 1816: || (lasttk==TSCOPE && lastval.pn == nn) ! 1817: || (lasttk==COMPL && dtor_seen == nn) ! 1818: || (lasttk==TYPE && lastval.t == TYPEDEF) ! 1819: || lasttk == NEW || in_sizeof ) ! 1820: { ! 1821: if ( nstd->n_tbl_list == 0 ) { // only one: ok ! 1822: break; ! 1823: } else { ! 1824: if (lasttk != TSCOPE && !ok){ ! 1825: error("ambiguous nested type %s, use X::%s",nn->string,nn->string); ! 1826: error( 'i', "cannot recover from previous errors" ); ! 1827: } ! 1828: } ! 1829: } ! 1830: } ! 1831: if ( nn->n_key != NESTED ) continue; ! 1832: if (xcl && strcmp(xcl->string,cl->string) == 0) break; ! 1833: } // end: for nn = nstd ! 1834: return nn; ! 1835: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.