|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/dcl2.c 1.6" */ ! 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: dcl2.c: ! 11: ! 12: *************************************************************************/ ! 13: ! 14: #include "cfront.h" ! 15: #include "size.h" ! 16: ! 17: Pname conv_dominates(Pname on1, Pname on2) ! 18: /* ! 19: compare for duplicates and dominance: ! 20: ! 21: on1 and on2 are two conversion operator functions ! 22: return the the one that dominates the other (according to the ! 23: class hierarchy) otherwise 0 (0 thus indicats ambiguous conversion) ! 24: */ ! 25: { ! 26: Ptype r1 = on1->tp->base==FCT ? Pfct(on1->tp)->returns ! 27: : Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns; ! 28: Ptype r2 = on2->tp->base==FCT ? Pfct(on2->tp)->returns ! 29: : Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns; ! 30: //error('d',"conv_dominates(%n,%n)",on1,on2); ! 31: if (r1==r2 || r1->check(r2,0)==0) return on1; ! 32: Pptr p1 = r1->is_ptr_or_ref(); ! 33: Pptr p2 = r2->is_ptr_or_ref(); ! 34: if (p1 && p2) { ! 35: Pname cn1 = p1->typ->is_cl_obj(); ! 36: Pname cn2 = p2->typ->is_cl_obj(); ! 37: if (cn1 && cn2) { ! 38: // is_cl_obj() returns b_name ! 39: // Pclass c1 = Pclass(Pbase(cn1->tp)->b_name->tp); ! 40: // Pclass c2 = Pclass(Pbase(cn2->tp)->b_name->tp); ! 41: Pclass c1 = Pclass(cn1->tp); ! 42: Pclass c2 = Pclass(cn2->tp); ! 43: if (c1 && c2) { ! 44: //if (c1==c2 || c1->has_base(c2)) ! 45: if (c1->has_base(c2)) ! 46: return on1; ! 47: else if (c2->has_base(c1)) ! 48: return on2; ! 49: } ! 50: } ! 51: } ! 52: return 0; ! 53: } ! 54: ! 55: ! 56: Pstmt curr_loop; ! 57: Pstmt curr_switch; ! 58: Pblock curr_block; ! 59: ! 60: void stmt::reached() ! 61: { ! 62: register Pstmt ss = s_list; ! 63: ! 64: if (ss == 0) return; ! 65: ! 66: switch (ss->base) { ! 67: case LABEL: ! 68: case CASE: ! 69: case DEFAULT: ! 70: break; ! 71: default: ! 72: error('w',&ss->where,"S after%k not reached",base); ! 73: for (; ss; ss=ss->s_list) { // delete unreacheable code ! 74: switch (ss->base) { ! 75: case LABEL: ! 76: case CASE: ! 77: case DEFAULT: // reachable ! 78: s_list = ss; ! 79: return; ! 80: case DCL: // the dcl may be used later ! 81: // keep to avoid cascading errors ! 82: case IF: ! 83: case DO: ! 84: case WHILE: ! 85: case SWITCH: ! 86: case FOR: ! 87: case BLOCK: // may hide a label ! 88: s_list = ss; ! 89: return; ! 90: } ! 91: } ! 92: s_list = 0; ! 93: } ! 94: } ! 95: ! 96: Pexpr check_cond(Pexpr e, TOK b, Ptable tbl) ! 97: { ! 98: //error('d',"check_cond(%k %k) tbl %d",e->base,b,tbl); ! 99: Pname cn; ! 100: if (e == dummy) error("empty condition for %k",b); ! 101: ! 102: int const_obj = 0; ! 103: const_obj = e->tp->tconst(); ! 104: Pexpr ee = e; ! 105: while (ee && (ee->base==DOT || ee->base==REF)) { ! 106: Pexpr m = ee->mem; ! 107: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 108: break; ! 109: ee = ee->e1; ! 110: } ! 111: if (ee) { ! 112: Ptype ttt = ee->tp; ! 113: switch (e->base) { ! 114: case REF: ! 115: Pptr p = ttt?ttt->is_ptr():0; ! 116: if (p && p->typ->tconst()) ! 117: const_obj = 1; ! 118: break; ! 119: case DOT: ! 120: if (ttt && ttt->tconst()) ! 121: const_obj = 1; ! 122: } ! 123: } ! 124: ! 125: if (cn = e->tp->is_cl_obj()) { ! 126: Pclass cl = Pclass(cn->tp); ! 127: int i = 0; ! 128: Pname found = 0; ! 129: for (Pname on = cl->conv; on; on=on->n_list) { ! 130: Pfct f = on->tp->base == FCT ? Pfct(on->tp) ! 131: : Pfct(Pgen(on->tp)->fct_list->f->tp); ! 132: Ptype t = f->returns->skiptypedefs(); ! 133: ! 134: switch (t->base) { ! 135: case PTR: ! 136: if (b == UMINUS) break; ! 137: case FLOAT: ! 138: case DOUBLE: ! 139: case LDOUBLE: ! 140: if (b == DEREF || b == SWITCH) break; ! 141: case CHAR: ! 142: case SHORT: ! 143: case INT: ! 144: case LONG: ! 145: case EOBJ: ! 146: // if (found==0 || found->tp->check(on->tp,0)) { ! 147: //error('d',"found %n on %n",found,on); ! 148: { Pname xx = found; ! 149: if (found == 0) { ! 150: i = 1; ! 151: found = on; ! 152: } ! 153: else if ((found = really_dominate(found,on,const_obj)) == 0) { ! 154: i = 2; ! 155: found = on; ! 156: error("two conversions for%nO in%kE: %n and %n",cn,b,xx,on); ! 157: return e; ! 158: } ! 159: } ! 160: } ! 161: } ! 162: //error('d',"i %d",i); ! 163: switch (i) { ! 164: case 0: ! 165: error("%nO in%kE",cn,b); ! 166: return e; ! 167: /* ! 168: case 1: ! 169: { Pname xx = new name(found->string); ! 170: Pref r = new ref(DOT,e,xx); ! 171: Pexpr rr = r->typ(tbl); ! 172: Pexpr c = new expr(G_CALL,rr,0); ! 173: ! 174: if (e->lval(0)) { ! 175: // Pref r = new ref(DOT,e,found); ! 176: // r->tp = found->tp; ! 177: // Pexpr c = new expr(G_CALL,r,0); ! 178: // c->fct_name = found; ! 179: return c->typ(tbl); ! 180: } ! 181: else { // (temp=init,temp.coerce()) ! 182: Pname tmp = make_tmp('U',e->tp,tbl); ! 183: Pexpr ass = init_tmp(tmp,e,tbl); ! 184: // Pref r = new ref(DOT,tmp,found); ! 185: // Pexpr rr = r->typ(tbl); ! 186: // Pexpr c = new expr(G_CALL,rr,0); ! 187: // c->fct_name = found; ! 188: ass = new expr(CM,ass,c); ! 189: return ass->typ(tbl); ! 190: } ! 191: } ! 192: */ ! 193: case 1: ! 194: { Pname xx = new name(found->string); ! 195: Pexpr c; ! 196: ! 197: if (e->lval(0)) { ! 198: Pref r = new ref(DOT,e,xx); ! 199: Pexpr rr = r->typ(tbl); ! 200: c = new expr(G_CALL,rr,0); ! 201: } ! 202: else { // (temp=init,temp.coerce()) ! 203: Pname tmp = make_tmp('U',e->tp,tbl); ! 204: Pexpr ass = init_tmp(tmp,e,tbl); ! 205: Pref r = new ref(DOT,tmp,xx); ! 206: Pexpr rr = r->typ(tbl); ! 207: c = new expr(G_CALL,rr,0); ! 208: c = new expr(CM,ass,c); ! 209: } ! 210: return c->typ(tbl); ! 211: } ! 212: // default: ! 213: // error("%d possible conversions for%nO in%kE",i,cn,b); ! 214: // return e; ! 215: } ! 216: ! 217: } ! 218: if (e->tp->memptr()) { ! 219: e = new mdot("i",e); ! 220: e->i1 = 9; ! 221: e = new expr(NE,e,zero); ! 222: } ! 223: else if (e->tp->num_ptr(b) == FCT) ! 224: error("%k(F)",b); ! 225: return e; ! 226: } ! 227: ! 228: void stmt::dcl() ! 229: /* ! 230: typecheck statement "this" in scope "curr_block->tbl" ! 231: */ ! 232: { ! 233: Pstmt ss; ! 234: Pname n; ! 235: Pname nn; ! 236: Pstmt ostmt = Cstmt; ! 237: DB( if(Ddebug>=1) error('d',&where,"'%k'->stmt::dcl()",base); ); ! 238: for (ss=this; ss; ss=ss->s_list) { ! 239: Pstmt old_loop, old_switch; ! 240: Cstmt = ss; ! 241: enum_promote = 0; ! 242: Ptable tbl = curr_block->memtbl; ! 243: //error('d',"stmt::dcl %k",ss->base); ! 244: switch (ss->base) { ! 245: case BREAK: ! 246: inline_restr |= 16; ! 247: if (curr_loop==0 && curr_switch==0) ! 248: error("break not in loop or switch"); ! 249: ss->reached(); ! 250: break; ! 251: ! 252: case CONTINUE: ! 253: inline_restr |= 32; ! 254: if (curr_loop == 0) error("continue not in loop"); ! 255: ss->reached(); ! 256: break; ! 257: ! 258: case DEFAULT: ! 259: if (curr_switch == 0) { ! 260: error("default not in switch"); ! 261: break; ! 262: } ! 263: if (curr_switch->has_default) error("two defaults in switch"); ! 264: curr_switch->has_default = ss; ! 265: ss->s->s_list = ss->s_list; ! 266: ss->s_list = 0; ! 267: ss->s->dcl(); ! 268: break; ! 269: ! 270: case SM: ! 271: { if (ss->e ==0) break; ! 272: TOK b = ss->e->base; ! 273: switch (b) { ! 274: case DUMMY: ! 275: ss->e = 0; ! 276: break; ! 277: // check for unused results ! 278: // don't check operators that are likely ! 279: // to be overloaded to represent "actions": ! 280: // ! ~ < <= > >= << >> ! 281: case EQ: ! 282: case NE: ! 283: case PLUS: ! 284: case MINUS: ! 285: case REF: ! 286: case DOT: ! 287: case MUL: ! 288: case DIV: ! 289: case ADDROF: ! 290: case AND: ! 291: case OR: ! 292: case ER: ! 293: case DEREF: ! 294: case ANDAND: ! 295: case OROR: ! 296: case NAME: ! 297: case VALUE: ! 298: if (ss->e->tp) break; // avoid looking at generated code ! 299: ss->e = ss->e->typ(tbl); ! 300: if (ss->e->base == CALL) break; ! 301: if (ss->e->tp->base != VOID) { ! 302: if ( ss->e->base == DEREF ) ! 303: error('w',"result of %sE not used",ss->e->e2?"[]":"*"); ! 304: else ! 305: error('w',"result of%kE not used",b); ! 306: if (ss->e->not_simple()==0) ss->e = dummy; ! 307: } ! 308: break; ! 309: default: ! 310: ss->e = ss->e->typ(tbl); ! 311: } ! 312: break; ! 313: } ! 314: case RETURN: ! 315: { Pname fn = cc->nof; ! 316: Pfct f = Pfct(fn->tp); ! 317: Ptype rt = f->returns->skiptypedefs(); ! 318: Pexpr v = ss->e; ! 319: //error('d',"rt %t",rt); ! 320: if (v != dummy) { ! 321: if (rt->base == RPTR || rt->base == PTR) { ! 322: const_ptr = Pbase(Pptr(rt)->typ)->tconst(); ! 323: } ! 324: if (rt->base == RPTR) { ! 325: ref_initializer++; ! 326: v = v->typ(tbl); ! 327: ref_initializer--; ! 328: } else ! 329: v = v->typ(tbl); ! 330: const_ptr = 0; ! 331: ! 332: if (fn->n_oper==CTOR ! 333: || fn->n_oper==DTOR ! 334: || (rt->base==VOID && v->tp!=void_type)) { ! 335: error("unexpected return value"); ! 336: // refuse to return the value: ! 337: ss->e = dummy; ! 338: } ! 339: else { ! 340: switch (rt->base) { ! 341: case RPTR: ! 342: switch (v->base) { ! 343: case NAME: ! 344: if (Pname(v)->n_scope==FCT ! 345: || Pname(v)->n_scope==ARG) ! 346: error('w',"R to localV returned"); ! 347: break; ! 348: case ICON: ! 349: case CCON: ! 350: case FCON: ! 351: case STRING: ! 352: if (Pptr(rt)->typ->tconst()==0) ! 353: error('w',"R to literal returned"); ! 354: } ! 355: v = ref_init(Pptr(rt),v,tbl); ! 356: if (v->base==G_CM ! 357: && v->e2->base==G_ADDROF ! 358: && v->e2->e2->base==NAME) ! 359: error('w',"R to temporary returned (return value is not lvalue or of wrongT)"); ! 360: case ANY: ! 361: break; ! 362: case COBJ: ! 363: if (v->base == DEREF) { ! 364: Pexpr v1 = v->e1; ! 365: if (v1->base==CAST) { ! 366: Pexpr v2 = v1->e1; ! 367: if (v2->base == G_CM) { // *(T)(e1,e2) => (e1,*(T)e2) ! 368: Pexpr v3 = v2->e2; ! 369: v2->e2 = v; ! 370: v2->tp = v->tp; ! 371: v = v2; ! 372: v1->e1 = v3; ! 373: } ! 374: } ! 375: } ! 376: if (f->f_result) { ! 377: if (v->base==G_CM && rt->check(v->tp,0/*ASSIGN*/)==0) ! 378: v = replace_temp(v,f->f_result); ! 379: else { ! 380: v = class_init(f->f_result->contents(),rt,v,tbl); ! 381: Pname rcn = rt->is_cl_obj(); ! 382: if (Pclass(rcn->tp)->has_itor()==0) { ! 383: // can happen for virtuals and for user defined conversions ! 384: v->tp = rt; ! 385: v = new expr(ASSIGN,f->f_result->contents(),v); ! 386: v->tp = rt; ! 387: } ! 388: } ! 389: } ! 390: else ! 391: v = class_init(0,rt,v,tbl); ! 392: break; ! 393: case PTR: ! 394: { Pexpr x = v; ! 395: v = ptr_init(Pptr(rt),v,tbl); ! 396: if (v->base == ADDROF ! 397: && v->e2->base == NAME ! 398: && Pname(v->e2)->n_stclass == AUTO) ! 399: error('w',"P to local variable%n returned",Pname(v->e2)); ! 400: // if (v==x ||v->e2==x) goto def; ! 401: if (Pchecked == 0) goto def; ! 402: goto ret_save; ! 403: // break; ! 404: } ! 405: case INT: ! 406: case CHAR: ! 407: case LONG: ! 408: case SHORT: ! 409: if (Pbase(rt)->b_unsigned ! 410: && v->base==UMINUS ! 411: && v->e2->base==ICON) ! 412: error('w',"negative returned fromF returning unsigned"); ! 413: default: ! 414: def: ! 415: { ! 416: Pexpr x = try_to_coerce(rt,v,"return value",tbl); ! 417: if (x) ! 418: v = x; ! 419: else if (rt->check(v->tp,ASSIGN)) ! 420: error("bad return valueT for%n:%t (%tX)",fn,v->tp,rt); ! 421: } ! 422: ! 423: } ! 424: ret_save: ! 425: ss->ret_tp = rt; ! 426: ss->e = v; ! 427: } ! 428: } ! 429: else { ! 430: if (rt->base != VOID) error("return valueX"); ! 431: } ! 432: ss->reached(); ! 433: break; ! 434: } ! 435: ! 436: case DO: // in DO the stmt is before the test ! 437: inline_restr |= 8; ! 438: old_loop = curr_loop; ! 439: curr_loop = ss; ! 440: { Pstmt st = ss->s; ! 441: while(st && st->base == FOR) st = st->for_init; ! 442: if (st && st->base == DCL) ! 443: if (st==ss->s) error("D as onlyS in do-loop"); ! 444: } ! 445: ss->s->dcl(); ! 446: ss->e = ss->e->typ(tbl); ! 447: ss->e = check_cond(ss->e,DO,tbl); ! 448: curr_loop = old_loop; ! 449: break; ! 450: ! 451: case WHILE: ! 452: inline_restr |= 8; ! 453: old_loop = curr_loop; ! 454: curr_loop = ss; ! 455: ss->e = ss->e->typ(tbl); ! 456: ss->e = check_cond(ss->e,WHILE,tbl); ! 457: { Pstmt st = ss->s; ! 458: while(st && st->base == FOR) st = st->for_init; ! 459: if (st && st->base == DCL) ! 460: if(st==ss->s) error("D as onlyS in while-loop"); ! 461: } ! 462: ss->s->dcl(); ! 463: curr_loop = old_loop; ! 464: break; ! 465: ! 466: case SWITCH: ! 467: { int ne = 0; ! 468: inline_restr |= 4; ! 469: old_switch = curr_switch; ! 470: curr_switch = ss; ! 471: ss->e = ss->e->typ(tbl); ! 472: ss->e = check_cond(ss->e,SWITCH,tbl); ! 473: { Pstmt st = ss->s; ! 474: while(st && st->base == FOR) st = st->for_init; ! 475: if (st && st->base == DCL) ! 476: if(st==ss->s) error("D as onlyS in switchS"); ! 477: } ! 478: { Ptype tt = ss->e->tp->skiptypedefs(); ! 479: ! 480: switch (tt->base) { ! 481: case EOBJ: ! 482: ne = Penum(Pbase(tt)->b_name->tp)->no_of_enumerators; ! 483: case ZTYPE: ! 484: case ANY: ! 485: case CHAR: ! 486: case SHORT: ! 487: case INT: ! 488: case LONG: ! 489: case FIELD: ! 490: break; ! 491: default: ! 492: error("%t switchE",ss->e->tp); ! 493: } ! 494: } ! 495: ss->s->dcl(); ! 496: if (ne) { /* see if the number of cases is "close to" ! 497: but not equal to the number of enumerators ! 498: */ ! 499: int i = 0; ! 500: Pstmt cs; ! 501: for (cs=ss->case_list; cs; cs=cs->case_list) i++; ! 502: if (i && i!=ne) { ! 503: if (ne < i) { ! 504: ee: error('w',"switch (%t)W %d cases (%d enumerators)",ss->e->tp,i,ne); ! 505: } ! 506: else { ! 507: switch (ne-i) { ! 508: case 1: if (3<ne) goto ee; ! 509: case 2: if (7<ne) goto ee; ! 510: case 3: if (23<ne) goto ee; ! 511: case 4: if (60<ne) goto ee; ! 512: case 5: if (99<ne) goto ee; ! 513: } ! 514: } ! 515: } ! 516: } ! 517: curr_switch = old_switch; ! 518: break; ! 519: } ! 520: case CASE: ! 521: if (curr_switch == 0) { ! 522: error("case not in switch"); ! 523: break; ! 524: } ! 525: ss->e = ss->e->typ(tbl); ! 526: ss->e->tp->num_ptr(CASE); ! 527: { Ptype tt = ss->e->tp->skiptypedefs(); ! 528: ! 529: switch (tt->base) { ! 530: case ZTYPE: ! 531: case ANY: ! 532: case CHAR: ! 533: case SHORT: ! 534: case INT: ! 535: case LONG: ! 536: case EOBJ: ! 537: Neval = 0; ! 538: long i = ss->e->eval(); ! 539: if (Neval == 0) { ! 540: Pstmt cs; ! 541: if (largest_int<i) error("long case value"); ! 542: for (cs=curr_switch->case_list; cs; cs=cs->case_list) { ! 543: if (cs->case_value == i) error("case %d used twice in switch",i); ! 544: } ! 545: ss->case_value = int(i); ! 546: ss->case_list = curr_switch->case_list; ! 547: curr_switch->case_list = ss; ! 548: } ! 549: else ! 550: error("bad case label: %s",Neval); ! 551: break; ! 552: default: ! 553: error("%t caseE",ss->e->tp); ! 554: } ! 555: } ! 556: // if (1) { ! 557: // Neval = 0; ! 558: // long i = ss->e->eval(); ! 559: // if (Neval == 0) { ! 560: // Pstmt cs; ! 561: // if (largest_int<i) error("long case value"); ! 562: // for (cs=curr_switch->case_list; cs; cs=cs->case_list) { ! 563: // if (cs->case_value == i) error("case %d used twice in switch",i); ! 564: // } ! 565: // ss->case_value = int(i); ! 566: // ss->case_list = curr_switch->case_list; ! 567: // curr_switch->case_list = ss; ! 568: // } ! 569: // else ! 570: // error("bad case label: %s",Neval); ! 571: // } ! 572: if (ss->s->s_list) error('i',"case%k",ss->s->s_list->base); ! 573: ss->s->s_list = ss->s_list; ! 574: ss->s_list = 0; ! 575: ss->s->dcl(); ! 576: break; ! 577: ! 578: case GOTO: ! 579: inline_restr |= 2; ! 580: ss->reached(); ! 581: case LABEL: ! 582: /* Insert label in function mem table; ! 583: labels have function scope. ! 584: */ ! 585: n = ss->d; ! 586: nn = cc->ftbl->insert(n,LABEL); ! 587: ! 588: /* Set a ptr to the mem table corresponding to the scope ! 589: in which the label actually occurred. This allows the ! 590: processing of goto's in the presence of ctors and dtors ! 591: */ ! 592: if (ss->base == LABEL) { ! 593: nn->n_realscope = curr_block->memtbl; ! 594: inline_restr |= 1; ! 595: } ! 596: ! 597: if (Nold) { ! 598: if (ss->base == LABEL) { ! 599: if (nn->n_initializer) error("twoDs of label%n",n); ! 600: nn->n_initializer = (Pexpr)1; ! 601: } ! 602: if (n != nn) ss->d = nn; ! 603: } ! 604: else { ! 605: if (ss->base == LABEL) nn->n_initializer = (Pexpr)1; ! 606: nn->where = ss->where; ! 607: } ! 608: if (ss->base == GOTO) ! 609: nn->use(); ! 610: else { ! 611: if (ss->s->s_list) error('i',"label%k",ss->s->s_list->base); ! 612: ss->s->s_list = ss->s_list; ! 613: ss->s_list = 0; ! 614: nn->assign(); ! 615: } ! 616: if (ss->s) ss->s->dcl(); ! 617: break; ! 618: ! 619: case IF: ! 620: { ! 621: Pexpr ee = ss->e->typ(tbl); ! 622: if (ee->base == ASSIGN) { ! 623: Neval = 0; ! 624: (void)ee->e2->eval(); ! 625: if (Neval == 0) ! 626: error('w',"constant assignment in condition"); ! 627: } ! 628: ss->e = ee = check_cond(ee,IF,tbl); ! 629: ! 630: if (ss->s->base == DCL) error("D as onlyS after `if'"); ! 631: ! 632: // pointer to member returns with a tp set to 0 ! 633: if ( ee->tp ) switch (ee->tp->base) { ! 634: case INT: ! 635: case EOBJ: ! 636: case ZTYPE: ! 637: { long i; ! 638: Neval = 0; ! 639: i = ee->eval(); ! 640: ! 641: if (Neval == 0) { ! 642: Pstmt sl = ss->s_list; ! 643: if (i) { ! 644: DEL(ss->else_stmt); ! 645: ss->s->dcl(); ! 646: *ss = *ss->s; ! 647: } ! 648: else { ! 649: DEL(ss->s); ! 650: if (ss->else_stmt) { ! 651: ss->else_stmt->dcl(); ! 652: *ss = *ss->else_stmt; ! 653: } ! 654: else { ! 655: ss->base = SM; ! 656: ss->e = dummy; ! 657: ss->s = 0; ! 658: } ! 659: } ! 660: ss->s_list = sl; ! 661: continue; ! 662: } ! 663: } ! 664: } ! 665: ss->s->dcl(); ! 666: if (ss->else_stmt) { ! 667: if (ss->else_stmt->base == DCL) error("D as onlyS after `else'"); ! 668: ss->else_stmt->dcl(); ! 669: } ! 670: break; ! 671: } ! 672: case FOR: ! 673: inline_restr |= 8; ! 674: old_loop = curr_loop; ! 675: curr_loop = ss; ! 676: if (ss->for_init) { ! 677: Pstmt fi = ss->for_init; ! 678: switch (fi->base) { ! 679: case SM: ! 680: if (fi->e == dummy) { ! 681: ss->for_init = 0; ! 682: break; ! 683: } ! 684: fi->dcl(); ! 685: break; ! 686: default: ! 687: // for (stmt; e1; e2) stmt1 stmt2 ! 688: // => {stmt; for(; e1; e2) stmt1 stmt2} ! 689: // if stmt != declaration ! 690: // if stmt == declaration, temporarily ! 691: // rewrite to avoid symbol table ! 692: // problems in some contexts. ! 693: // Then put decl back to avoid ! 694: // extraneous {}. ! 695: // Note: to maintain pointers, ss ! 696: // must not change ! 697: { Pstmt tmp = new stmt (SM,curloc,0); ! 698: *tmp = *ss; // tmp = original for ! 699: tmp->for_init = 0; ! 700: fi->s_list = tmp; ! 701: *ss = *fi; ! 702: curr_loop = old_loop; ! 703: ss->dcl(); ! 704: tmp = ss->s_list; ! 705: if ( ss->base == DCL ! 706: && tmp->base == FOR // sanity check ! 707: && tmp->for_init == 0 // sanity check ! 708: ) { ! 709: // put DCL back in for init ! 710: *fi = *ss; ! 711: *ss = *tmp; ! 712: ss->for_init = fi; ! 713: fi->s_list = 0; ! 714: } else { ! 715: // non-decl stmt in for init ! 716: // put stmts in block in case ! 717: // they follow a condition... ! 718: // allocate tmp to be sure ! 719: // fields are initialized ! 720: *fi = *ss; ! 721: tmp = new block(ss->where,0,fi); ! 722: tmp->own_tbl = 0; ! 723: tmp->memtbl = curr_block->memtbl; ! 724: tmp->permanent = ss->permanent; ! 725: *ss = *tmp; ! 726: tmp->permanent = 0; delete tmp; ! 727: } ! 728: // don't repeat stmt::dcl() for ! 729: // remaining stmts ! 730: goto done; ! 731: } ! 732: } ! 733: } ! 734: if (ss->e == dummy) ! 735: ss->e = 0; ! 736: else { ! 737: ss->e = ss->e->typ(tbl); ! 738: ss->e = check_cond(ss->e,FOR,tbl); ! 739: } ! 740: { Pstmt st = ss->s; ! 741: while(st && st->base == FOR) st = st->for_init; ! 742: if (st && st->base == DCL) ! 743: if(st==ss->s) error("D as onlyS in for-loop"); ! 744: } ! 745: ss->s->dcl(); ! 746: ss->e2 = (ss->e2 == dummy) ? 0 : ss->e2->typ(tbl); ! 747: curr_loop = old_loop; ! 748: break; ! 749: ! 750: case DCL: /* declaration after statement */ ! 751: { ! 752: /* collect all the contiguous DCL nodes from the ! 753: head of the s_list. find the next statement ! 754: */ ! 755: int non_trivial = 0; ! 756: int count = 0; ! 757: Pname tail = ss->d; ! 758: for (Pname nn=tail; nn; nn=nn->n_list) { ! 759: // find tail; ! 760: // detect non-trivial declarations ! 761: count++; ! 762: ! 763: if (nn->n_list) tail = nn->n_list; ! 764: Pname n = tbl->look(nn->string,0); ! 765: ! 766: if (n && n->n_table==tbl) non_trivial = 2; ! 767: if (non_trivial == 2) continue; ! 768: if ((nn->n_sto==STATIC && nn->tp->base!=FCT) ! 769: || nn->tp->is_ref() ! 770: || (nn->tp->tconst() && fct_const==0)) { ! 771: non_trivial = 2; ! 772: continue; ! 773: } ! 774: ! 775: Pexpr in = nn->n_initializer; ! 776: if (in) ! 777: switch (in->base) { ! 778: case ILIST: ! 779: case STRING: ! 780: non_trivial = 2; ! 781: continue; ! 782: } ! 783: non_trivial = 1; ! 784: Pname cln = nn->tp->is_cl_obj(); ! 785: if (cln == 0) cln = cl_obj_vec; ! 786: if (cln == 0) continue; ! 787: if (Pclass(cln->tp)->has_ctor()) { ! 788: non_trivial = 2; ! 789: continue; ! 790: } ! 791: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2; ! 792: } ! 793: ! 794: while( ss->s_list && ss->s_list->base==DCL ) { ! 795: Pstmt sx = ss->s_list; ! 796: tail = tail->n_list = sx->d; // add to tail ! 797: for (nn=sx->d; nn; nn=nn->n_list) { ! 798: // find tail; ! 799: // detect non-trivial declarations ! 800: count++; ! 801: if (nn->n_list) tail = nn->n_list; ! 802: Pname n = tbl->look(nn->string,0); ! 803: if (n && n->n_table==tbl) non_trivial = 2; ! 804: if (non_trivial == 2) continue; ! 805: if ((nn->n_sto==STATIC && nn->tp->base!=FCT) ! 806: || nn->tp->is_ref() ! 807: || (nn->tp->tconst() && fct_const==0)) { ! 808: non_trivial = 2; ! 809: continue; ! 810: } ! 811: Pexpr in = nn->n_initializer; ! 812: if (in) ! 813: switch (in->base) { ! 814: case ILIST: ! 815: case STRING: ! 816: non_trivial = 2; ! 817: continue; ! 818: } ! 819: non_trivial = 1; ! 820: Pname cln = nn->tp->is_cl_obj(); ! 821: if (cln == 0) cln = cl_obj_vec; ! 822: if (cln == 0) continue; ! 823: if (Pclass(cln->tp)->has_ctor()) { ! 824: non_trivial = 2; ! 825: continue; ! 826: } ! 827: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2; ! 828: } ! 829: ss->s_list = sx->s_list; ! 830: /* delete sx; */ ! 831: } ! 832: ! 833: Pstmt next_st = ss->s_list; ! 834: //error('d',"dcl stmt : d %n non_trivial %d curr own_tbl %d inline_restr 0%o",ss->d,non_trivial,curr_block->own_tbl,inline_restr); ! 835: if (non_trivial==2 // must ! 836: || (non_trivial==1 // might ! 837: && ( curr_block->own_tbl==0 // why not? ! 838: || inline_restr&3 /* label seen */) ! 839: ) ! 840: ) { ! 841: if (curr_switch && non_trivial==2) { ! 842: Pstmt cs = curr_switch->case_list; ! 843: Pstmt ds = curr_switch->has_default; ! 844: Pstmt bl; ! 845: if (cs == 0) ! 846: bl = ds; ! 847: else if (ds == 0) ! 848: bl = cs; ! 849: else if (cs->where.line<ds->where.line) ! 850: bl = ds; ! 851: else ! 852: bl = cs; ! 853: ! 854: if ((bl==0 || bl->s->base!=BLOCK) && curr_switch->s->memtbl==tbl) ! 855: error('s',"non trivialD in switchS (try enclosing it in a block)"); ! 856: } ! 857: ! 858: /* Create a new block, ! 859: put all the declarations at the head, ! 860: and the remainder of the slist as the ! 861: statement list of the block. ! 862: */ ! 863: //ss->base = BLOCK; //DCL ! 864: ! 865: /* check that there are no redefinitions ! 866: since the last "real" (user-written, ! 867: non-generated) block ! 868: */ ! 869: { Pname lastnn = 0; ! 870: for( nn=ss->d; nn; nn=nn->n_list ) { ! 871: Pname n; ! 872: //n=curr_block->memtbl->look(nn->string,0); ! 873: //error('d',"checking %n lex_level: %d n: %n n->lex_level: %d",nn,nn->lex_level,n,n?n->lex_level:0); ! 874: //error('d'," own_tbl: %d curr_block: %d n->n_table: %d",curr_block->own_tbl,curr_block,n->n_table); ! 875: //error('d'," real_block: %d n's real_block: %d",curr_block->memtbl->real_block,n->n_table->real_block); ! 876: //if( curr_block->own_tbl ! 877: if ( (n=curr_block->memtbl->look(nn->string,0)) ! 878: && n->n_table->real_block==curr_block->memtbl->real_block ! 879: && n->tp->base!=FCT ! 880: && n->tp->base!=OVERLOAD ! 881: && nn->lex_level == n->lex_level ) { ! 882: error("twoDs of%n",n); ! 883: if (lastnn==0) ss->d=nn->n_list; ! 884: else lastnn->n_list=nn->n_list; ! 885: } else lastnn = nn; ! 886: } // for nn ! 887: } ! 888: ! 889: /* attach the remainder of the s_list ! 890: as the statement part of the block. ! 891: */ ! 892: ss->s = next_st; ! 893: ss->s_list = 0; ! 894: ! 895: /* create the table in advance, ! 896: in order to set the real_block ! 897: ptr to that of the enclosing table ! 898: */ ! 899: ss->memtbl = new table(count+4,tbl,0); ! 900: ss->memtbl->real_block = curr_block->memtbl->real_block; ! 901: Pblock(ss)->dcl(ss->memtbl); ! 902: } ! 903: else { /* to reduce the number of symbol tables, ! 904: do not make a new block, ! 905: instead insert names in enclosing block, ! 906: and make the initializers into expression ! 907: statements. ! 908: */ ! 909: Pstmt sss = ss; ! 910: { Pname lastnn = 0; ! 911: for( nn=ss->d; nn; nn=nn->n_list ) { ! 912: Pname n; ! 913: //error('d',"nn %n",nn); ! 914: //if( curr_block->own_tbl ! 915: if ( (n=curr_block->memtbl->look(nn->string,0)) ! 916: && n->n_table->real_block==curr_block->memtbl->real_block ! 917: && n->tp->base!=FCT && n->tp->base!=OVERLOAD ! 918: && nn->lex_level == n->lex_level ) { ! 919: error("twoDs of%n",n); ! 920: n = 0; ! 921: if (lastnn==0) ss->d=nn->n_list; ! 922: else lastnn->n_list=nn->n_list; ! 923: } else { ! 924: n = nn->dcl(tbl,FCT); ! 925: lastnn=nn; ! 926: } ! 927: ! 928: if (n == 0) { ! 929: if (ss) { ! 930: ss->base = SM; ! 931: ss->e = 0; ! 932: } ! 933: continue; ! 934: } ! 935: //error('d',"hoisted %n to outer blk",n); ! 936: ! 937: Pexpr in = n->n_initializer; ! 938: n->n_initializer = 0; ! 939: ! 940: if (ss) { ! 941: sss->base = SM; ! 942: ss = 0; ! 943: } ! 944: else ! 945: sss = sss->s_list = new estmt(SM,sss->where,0,0); ! 946: if (in) { ! 947: switch (in->base) { ! 948: case G_CALL: /* constructor? */ ! 949: { ! 950: Pname fn = in->fct_name; ! 951: if (fn && fn->n_oper==CTOR) break; ! 952: } ! 953: default: ! 954: in = new expr(ASSIGN,n,in); ! 955: in->tp = n->tp; ! 956: } ! 957: // sss->e = in->typ(tbl); ! 958: sss->e = in; ! 959: sss->where=n->where; ! 960: } ! 961: else ! 962: sss->e = dummy; ! 963: } // for nn ! 964: } ! 965: ! 966: ss = sss; ! 967: ss->s_list = next_st; ! 968: } ! 969: break; ! 970: } ! 971: ! 972: case BLOCK: ! 973: Pblock(ss)->dcl(tbl); ! 974: break; ! 975: ! 976: case ASM: ! 977: /* save string */ ! 978: { ! 979: char* s = (char*)ss->e; ! 980: int ll = strlen(s); ! 981: char* s2 = new char[ll+1]; ! 982: strcpy(s2,s); ! 983: ss->e = Pexpr(s2); ! 984: break; ! 985: } ! 986: default: ! 987: error('i',"badS(%p %d)",ss,ss->base); ! 988: } ! 989: } ! 990: done: ! 991: Cstmt = ostmt; ! 992: } ! 993: ! 994: void block::dcl(Ptable tbl) ! 995: /* ! 996: Note: for a block without declarations memtbl denotes the table ! 997: for the enclosing scope. ! 998: A function body has its memtbl created by fct::dcl(). ! 999: */ ! 1000: { ! 1001: int bit_old = bit_offset; ! 1002: int byte_old = byte_offset; ! 1003: int max_old = max_align; ! 1004: Pblock block_old = curr_block; ! 1005: ! 1006: if (base != BLOCK && base != DCL) error('i',"block::dcl(%d)",base); ! 1007: ! 1008: curr_block = this; ! 1009: //error('d',"%d->block::dcl(%d) base %k",this,tbl,base); ! 1010: //error('d'," memtbl %d own_tbl %d d %n s %k",memtbl,own_tbl,d,s?s->base:0); ! 1011: if (d) { ! 1012: own_tbl = 1; ! 1013: base = BLOCK; ! 1014: if (memtbl == 0) { ! 1015: int nmem = d->no_of_names()+4; ! 1016: memtbl = new table(nmem,tbl,0); ! 1017: memtbl->real_block = this; ! 1018: /* this is a "real" block from the ! 1019: source text, and not one created by DCL's ! 1020: inside a block. */ ! 1021: } ! 1022: else ! 1023: if (memtbl != tbl) error('i',"block::dcl(?)"); ! 1024: ! 1025: Pname nx; ! 1026: for (Pname n=d; n; n=nx) { ! 1027: nx = n->n_list; ! 1028: n->dcl(memtbl,FCT); ! 1029: switch (n->tp->base) { ! 1030: case CLASS: ! 1031: case ANON: ! 1032: case ENUM: ! 1033: break; ! 1034: default: ! 1035: delete n; ! 1036: } ! 1037: } ! 1038: } ! 1039: else if ( base == BLOCK ) { ! 1040: own_tbl = 1; ! 1041: if (memtbl == 0) { ! 1042: int nmem = 4; ! 1043: memtbl = new table(nmem,tbl,0); ! 1044: memtbl->real_block = this; ! 1045: /* this is a "real" block from the ! 1046: source text, and not one created by DCL's ! 1047: inside a block. */ ! 1048: } else ! 1049: if (memtbl != tbl) error('i',"block::dcl(?)"); ! 1050: } else { ! 1051: base = BLOCK; ! 1052: memtbl = tbl; ! 1053: } ! 1054: ! 1055: Pname odcl = Cdcl; ! 1056: if (s) s->dcl(); ! 1057: if (own_tbl) { ! 1058: Pname m; ! 1059: int i; ! 1060: for (m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i)) { ! 1061: Ptype t = m->tp; ! 1062: ! 1063: if (in_class_dcl) m->lex_level -= 1; ! 1064: ! 1065: if (t == 0) { ! 1066: if (m->n_assigned_to == 0) ! 1067: error("label %sU",m->string); ! 1068: if (m->n_used == 0) ! 1069: error('w',"label %s not used", m->string); ! 1070: continue; ! 1071: } ! 1072: ! 1073: t = t->skiptypedefs(); ! 1074: ! 1075: switch (t->base) { ! 1076: case CLASS: ! 1077: case ANON: ! 1078: case ENUM: ! 1079: case FCT: ! 1080: //case VEC: ! 1081: continue; ! 1082: } ! 1083: ! 1084: if (m->n_addr_taken == 0) { ! 1085: if (m->n_used) { ! 1086: if (m->n_assigned_to) { ! 1087: } ! 1088: else if ( t->base != VEC ) { ! 1089: switch (m->n_scope) { ! 1090: case FCT: ! 1091: Cdcl = m; ! 1092: if (m->string[0] != '_' && m->string[1] != '_' ) ! 1093: error('w',&m->where,"%n used but not set",m); ! 1094: } ! 1095: } ! 1096: } ! 1097: else { ! 1098: if (m->n_assigned_to) { ! 1099: } ! 1100: else if (m->string[0]!='_' || m->string[1]!='_') { ! 1101: switch (m->n_scope) { ! 1102: case ARG: ! 1103: case FCT: ! 1104: Cdcl = m; ! 1105: error('w',&m->where,"%n not used",m); ! 1106: } ! 1107: } ! 1108: } ! 1109: } ! 1110: } ! 1111: } ! 1112: Cdcl = odcl; ! 1113: ! 1114: d = 0; ! 1115: ! 1116: if (bit_offset) byte_offset += SZ_WORD; ! 1117: bit_offset = bit_old; ! 1118: byte_offset = byte_old; ! 1119: curr_block = block_old; ! 1120: } ! 1121: ! 1122: void name::field_align() ! 1123: /* ! 1124: adjust alignment ! 1125: */ ! 1126: { ! 1127: Pbase fld = (Pbase)tp; ! 1128: int nbits = fld->b_bits; ! 1129: ! 1130: int a = (F_SENSITIVE) ? fld->b_fieldtype->align() : SZ_WORD; ! 1131: if (max_align < a) max_align = a; ! 1132: ! 1133: if (nbits == 0) { // force word alignment ! 1134: int b; ! 1135: if (bit_offset) ! 1136: nbits = BI_IN_WORD - bit_offset; ! 1137: else if (b = byte_offset%SZ_WORD) ! 1138: nbits = b * BI_IN_BYTE; ! 1139: // else ! 1140: // nbits = BI_IN_WORD; ! 1141: if (max_align < SZ_WORD) max_align = SZ_WORD; ! 1142: } ! 1143: else if (bit_offset == 0) { // take care of part of word ! 1144: int b = byte_offset%SZ_WORD; ! 1145: if (b) { ! 1146: byte_offset -= b; ! 1147: bit_offset = b*BI_IN_BYTE; ! 1148: } ! 1149: } ! 1150: //error('d',"byteoff %d bitoff %d bits %d",byte_offset,bit_offset,nbits); ! 1151: int x = (bit_offset += nbits); ! 1152: if (BI_IN_WORD < x) { ! 1153: fld->b_offset = 0; ! 1154: byte_offset += SZ_WORD; ! 1155: bit_offset = nbits; ! 1156: } ! 1157: else { ! 1158: fld->b_offset = bit_offset; ! 1159: if (BI_IN_WORD == x) { ! 1160: bit_offset = 0; ! 1161: byte_offset += SZ_WORD; ! 1162: } ! 1163: else ! 1164: bit_offset = x; ! 1165: } ! 1166: n_offset = byte_offset; ! 1167: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.