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