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