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