|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/expr.c 1.8" */ ! 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: expr.c: ! 11: ! 12: type check expressions ! 13: ! 14: ************************************************************************/ ! 15: ! 16: #include "cfront.h" ! 17: #include "size.h" ! 18: ! 19: int const_save; ! 20: int const_ptr; ! 21: extern Ptype Pfct_type; ! 22: ! 23: Pexpr expr::address() ! 24: { ! 25: // error('d',"address %k %d %s",base,base,base==NAME||base==ANAME?string:"?"); ! 26: // error('d',"address e1 %d %k e2 %d %k", e1, e1?e1->base:0, e2, e2?e2->base:0); ! 27: switch (base) { ! 28: case DEREF: ! 29: if (e2 == 0) return e1; // &*e => e ! 30: break; ! 31: case QUEST: // &(a?b:c) => a?&b:&c ! 32: e1 = e1->address(); ! 33: // no break; ! 34: case G_CM: ! 35: if ( e1 && e1->base == G_CALL && ! 36: e2 && e2->base == G_ADDROF) ! 37: return this; ! 38: case CM: ! 39: e2 = e2->address(); // &(e1,e2) => (e1,&e2) ! 40: tp = e2->tp; //LLL ! 41: return this; ! 42: case INCR: ! 43: case DECR: // &(++a) => (++a,&a) ! 44: if (e1) break; ! 45: nin++; ! 46: if (e2->not_simple()) error('s',"& of%k",base); ! 47: nin--; ! 48: e1 = new expr(base,0,e2); ! 49: e2 = e2->address(); ! 50: base = G_CM; ! 51: tp = e2->tp; ! 52: return this; ! 53: case ASSIGN: // &(a=b) => ((a=b),&a) ! 54: case ASPLUS: ! 55: case ASMINUS: ! 56: case ASMUL: ! 57: case ASDIV: ! 58: case ASMOD: ! 59: case ASAND: ! 60: case ASOR: ! 61: case ASER: ! 62: case ASLS: ! 63: case ASRS: ! 64: nin++; ! 65: if (e1->not_simple()) error('s',"& of%k",base); ! 66: nin--; ! 67: Pexpr a = new expr(base,e1,e2); ! 68: a->tp = a->e1->tp; ! 69: base = G_CM; ! 70: e1 = a; ! 71: e2 = a->e1->address(); ! 72: tp = e2->tp; ! 73: return this; ! 74: ! 75: case NAME: ! 76: if (Pname(this)->n_stclass == REGISTER) error("& register%n",Pname(this)); ! 77: Pname(this)->take_addr(); ! 78: break; ! 79: case CALL: ! 80: case CAST: ! 81: case NEW: ! 82: case GNEW: ! 83: if (tp && tp->is_ptr_or_ref()) { // hack? ! 84: return this; ! 85: } ! 86: break; ! 87: } ! 88: ! 89: register Pexpr ee = new expr(G_ADDROF,0,this); ! 90: if (tp) { // tp==0 ??? ! 91: ee->tp = tp->addrof(); ! 92: ! 93: switch (tp->base) { ! 94: case PTR: ! 95: Pptr(ee->tp)->memof = Pptr(tp)->memof; ! 96: break; ! 97: case FCT: ! 98: if (Pfct(tp)->f_static==0) ! 99: Pptr(ee->tp)->memof = Pfct(tp)->memof; ! 100: break; ! 101: case OVERLOAD: ! 102: if (Pfct(Pgen(tp)->fct_list->f->tp)->f_static==0) ! 103: Pptr(ee->tp)->memof = Pfct(Pgen(tp)->fct_list->f->tp)->memof; ! 104: } ! 105: } ! 106: ! 107: return ee; ! 108: } ! 109: ! 110: Pexpr expr::contents() ! 111: { ! 112: //error('d',"deref %k %d %t",base,base,tp); ! 113: // if (base==ADDROF || base==G_ADDROF) return e2; // *& ! 114: switch (base) { ! 115: case ADDROF: ! 116: case G_ADDROF: ! 117: return e2; // *& ! 118: case ELIST: ! 119: //error('d',"contents of elist"); ! 120: e1 = e1->contents(); ! 121: tp = e1->tp; ! 122: return this; ! 123: }; ! 124: ! 125: register Pexpr ee = new expr(DEREF,this,0); ! 126: if (tp) { // tp==0 ??? ! 127: Ptype tt = tp; ! 128: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp; ! 129: ee->tp = Pptr(tt)->typ; ! 130: Pname cn = ee->tp->is_cl_obj(); ! 131: if (cn) { ! 132: Pclass cl = Pclass(cn->tp); ! 133: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl ! 134: } ! 135: } ! 136: return ee; ! 137: } ! 138: ! 139: static Pexpr ! 140: make_postfix( Pexpr op ) ! 141: { // apply the postfix form of increment/decrement operator ! 142: Pexpr e = op->e1->base==NAME?op->e1:op->e1->mem; ! 143: for (Plist fl=Pgen(e->tp)->fct_list;fl; fl=fl->l) { ! 144: Pname n = fl->f; ! 145: Pfct f = Pfct(n->tp); ! 146: if ((f->nargs==1 && f->f_this) || ! 147: (f->nargs==2 && f->f_this==0)) { ! 148: ! 149: if (op->e1->base == NAME) { ! 150: op->e1 = n; ! 151: op->e2->e2 = new expr(ELIST,zero,0); ! 152: } else { ! 153: op->e1->mem = n; ! 154: op->e2 = new expr(ELIST,zero,0); ! 155: } ! 156: ! 157: op->fct_name = n; ! 158: n->dcl_print(0); ! 159: return op; ! 160: } ! 161: } ! 162: error('w',"no postfix instance of%n, although overloaded",Pname(e)); ! 163: return op; // as it were ! 164: } ! 165: ! 166: int bound; ! 167: int chars_in_largest; // no of characters in largest int ! 168: static Pclass mpglob; ! 169: ! 170: Pexpr expr::typ(Ptable tbl) ! 171: /* ! 172: find the type of "this" and place it in tp; ! 173: return the typechecked version of the expression: ! 174: "tbl" provides the scope for the names in "this" ! 175: */ ! 176: { ! 177: //if (this == 0) error('i',"0->expr::typ"); ! 178: Pname n; ! 179: Ptype t = 0; ! 180: Ptype t1, t2; ! 181: TOK b = base; ! 182: TOK r1, r2; ! 183: #define nppromote(b) t=np_promote(b,r1,r2,t1,t2,1) ! 184: #define npcheck(b) (void)np_promote(b,r1,r2,t1,t2,0) ! 185: if (tbl->base != TABLE) error('i',"expr::typ(%d)",tbl->base); ! 186: ! 187: DB( if(Tdebug>=1) { ! 188: error('d',"%d->expr::typ(%d) %k %t",this,tbl,b,tp); ! 189: display_expr(this); ! 190: }); ! 191: // error('d',"%k->typ %n tp: %t", b,b==NAME?this:0,tp); ! 192: // error('d'," e1 %d %k e1 %d %k",e1,e1?e1->base:0,e2,e2?e2->base:0); ! 193: ! 194: if (tp) { ! 195: switch (b) { ! 196: case NAME: ! 197: //?? Pname(this)->use(); ! 198: break; ! 199: case MDOT: ! 200: mem = mem->typ(tbl); ! 201: } ; ! 202: // if (b == NAME) Pname(this)->use(); ! 203: return this; ! 204: } ! 205: ! 206: extern Pname Ntmp; ! 207: ! 208: switch (b) { // is it a basic type ! 209: case MDOT: ! 210: error('i',"mdot %s",string2); ! 211: case DUMMY: ! 212: error("emptyE"); ! 213: tp = any_type; ! 214: return this; ! 215: ! 216: case ZERO: ! 217: tp = zero_type; ! 218: return this; ! 219: ! 220: case IVAL: ! 221: tp = int_type; ! 222: return this; ! 223: ! 224: //case FVAL: ! 225: // tp = float_type; ! 226: // return this; ! 227: ! 228: case ICON: ! 229: /* is it long? ! 230: explicit long? ! 231: decimal larger than largest signed int ! 232: octal or hexadecimal larger than largest unsigned int ! 233: */ ! 234: { int ll = strlen(string); ! 235: switch (string[ll-1]) { ! 236: case 'l': ! 237: case 'L': ! 238: switch (string[ll-2]) { ! 239: case 'u': ! 240: case 'U': ! 241: string[ll-2] = 0; ! 242: tp = ulong_type; ! 243: goto cast_n_save; ! 244: } ! 245: lng: ! 246: tp = long_type; ! 247: goto save; ! 248: case 'u': ! 249: case 'U': // 1u => unsigned(1) ! 250: switch (string[ll-2]) { ! 251: case 'l': ! 252: case 'L': ! 253: string[ll-2] = 0; ! 254: ulng: ! 255: tp = ulong_type; ! 256: goto cast_n_save; ! 257: default: ! 258: string[ll-1] = 0; ! 259: uint: ! 260: tp = uint_type; ! 261: goto cast_n_save; ! 262: } ! 263: } ! 264: ! 265: // no suffix - see if we can figure it out ! 266: if (string[0] == '0') { // assume 8 bits in byte ! 267: register index = 1; ! 268: switch (string[1]) { ! 269: case 'x': ! 270: case 'X': ! 271: while(string[++index]=='0') ; ! 272: ll -= index; ! 273: int HSZ = SZ_INT+SZ_INT; ! 274: if(ll < HSZ) goto nrm; ! 275: if(ll == HSZ) ! 276: if(string[2]>='8') goto uint; ! 277: else goto nrm; ! 278: if(SZ_INT==SZ_LONG) break; ! 279: HSZ = SZ_LONG+SZ_LONG; ! 280: if(ll < HSZ) goto lng; ! 281: if(ll == HSZ) ! 282: if(string[2]>='8') goto ulng; ! 283: else goto lng; ! 284: break; ! 285: default: // OCTAL ! 286: register IBITS = BI_IN_BYTE*SZ_INT; ! 287: while(string[index]=='0') index++; ! 288: register char x = string[index]; ! 289: int lbt = x=='1' ? 1 : ! 290: ( x=='2' || x=='3' ? 2 : 3 ); ! 291: int nbits = (ll-index-1)*3 + lbt; ! 292: if(nbits < IBITS) goto nrm; ! 293: if(nbits == IBITS) goto uint; ! 294: if(nbits < BI_IN_BYTE*SZ_LONG) goto lng; ! 295: } ! 296: goto ulng; ! 297: } ! 298: else { // DECIMAL ! 299: if (ll<chars_in_largest) { ! 300: nrm: ! 301: tp = int_type; ! 302: goto save; ! 303: } ! 304: if (ll>chars_in_largest) { ! 305: if(SZ_INT==SZ_LONG || ll>2*chars_in_largest) ! 306: goto ulng; ! 307: goto lng; ! 308: } ! 309: // ll == chars_in_largest ! 310: char* p = string; ! 311: char* q = LARGEST_INT; ! 312: do if (*p>*q) { ! 313: if(SZ_INT==SZ_LONG) goto ulng; ! 314: goto lng; ! 315: } while (*p++==*q++ && *p); ! 316: } ! 317: ! 318: goto nrm; ! 319: } ! 320: case CCON: ! 321: tp = c_strlen(string)<5 ? char_type : int_type; // stored as 'a' ! 322: goto save; ! 323: ! 324: case FCON: ! 325: { int ll = strlen(string); ! 326: int last = string[ll-1]; ! 327: tp = double_type; ! 328: if (last=='F' || last=='f') { ! 329: tp = float_type; ! 330: if (!ansi_opt) { ! 331: string[ll-1] = 0; ! 332: goto cast_n_save; ! 333: } ! 334: } ! 335: else if (last=='L' || last=='l') { ! 336: if (ansi_opt == 0) string[ll-1] = 0; ! 337: tp = ldouble_type; ! 338: } ! 339: goto save; ! 340: } ! 341: case STRING: // type of "as\tdf" is char[6] ! 342: // c_strlen counts the terminating '\0' ! 343: { Pvec v = new vec(char_type,0); ! 344: v->size = c_strlen(string); ! 345: tp = v; ! 346: } ! 347: save: ! 348: if (const_save) { // "as\tdf" needs 7 chars for storage ! 349: char* p = new char[strlen(string)+1]; ! 350: strcpy(p,string); ! 351: string = p; ! 352: } ! 353: ! 354: return this; ! 355: ! 356: cast_n_save: ! 357: if (const_save) { // "as\tdf" needs 7 chars for storage ! 358: char* p = new char[strlen(string)+1]; ! 359: strcpy(p,string); ! 360: string = p; ! 361: } ! 362: ! 363: return new cast(tp,this); ! 364: ! 365: case THIS: ! 366: delete this; ! 367: if (cc->c_this) { ! 368: cc->c_this->use(); ! 369: return cc->c_this; ! 370: } ! 371: error("``this'' used in nonC context"); ! 372: n = new name("this"); ! 373: n->tp = any_type; ! 374: return tbl->insert(n,0); ! 375: ! 376: case NAME: ! 377: { ! 378: Pname q = Pname(this)->n_qualifier; // suppress virtual iff x:: ! 379: Pexpr ee = find_name(Pname(this),cc->cot,tbl,0,cc->nof); ! 380: if (q && (ee->base==REF || ee->base==DOT)) ! 381: ee->n_initializer = Pexpr(q); ! 382: //error('d',"ee %k %t %n",ee->base,ee->tp,ee->base==NAME?ee:ee->base==REF?ee->mem:0); ! 383: // if (ee->tp->base == RPTR) return ee->contents(); ! 384: if (ee->tp->is_ref()) return ee->contents(); ! 385: ! 386: if (ee->base==NAME && Pname(ee)->n_xref) { ! 387: // fudge to handle X(X&) args ! 388: ee = new expr(DEREF,ee,0); ! 389: ee->tp = ee->e1->tp; // !! ! 390: } ! 391: ! 392: return ee; ! 393: } ! 394: ! 395: case ADDROF: ! 396: case G_ADDROF: // handle lookup for &s::i ! 397: mpglob = 0; ! 398: if (e2->base == NAME) e2 = find_name(Pname(e2),cc->cot,tbl,ADDROF,cc->nof); ! 399: if (e2->base==NAME && Pname(e2)->n_xref) { ! 400: // fudge to handle X(X&) args ! 401: e2 = new expr(DEREF,e2,0); ! 402: e2->tp = e2->e1->tp; // !! ! 403: } ! 404: if (e2->base==DOT) { // &f().x = > &(tmp=f(),&tmp)->x ! 405: switch (e2->e1->base) { ! 406: case CALL: ! 407: case G_CALL: ! 408: case VALUE: ! 409: error("& non-lvalue"); ! 410: } ! 411: } ! 412: break; ! 413: ! 414: case SIZEOF: ! 415: if (tp2) { ! 416: tp2->dcl(tbl); ! 417: switch (tp2->base) { ! 418: case VOID: ! 419: error("sizeof(void)"); ! 420: break; ! 421: case CLASS: ! 422: { ! 423: Pclass cl = Pclass(tp2); ! 424: if (cl->c_body==1 ! 425: && (cl->defined&(DEFINED|SIMPLIFIED)) == 0) ! 426: error('s',"class defined within sizeof"); ! 427: } ! 428: } ! 429: ! 430: if (e1 && e1!=dummy) { ! 431: e1 = e1->typ(tbl); ! 432: DEL(e1); ! 433: e1 = dummy; ! 434: } ! 435: Pptr r = tp2->is_ref(); ! 436: if (r) tp2 = r->typ; // sizeof(T&)==sizeof(T) ! 437: } ! 438: else if (e1 == dummy) { ! 439: error("sizeof emptyE"); ! 440: tp = any_type; ! 441: return this; ! 442: } ! 443: else { ! 444: e1 = e1->typ(tbl); ! 445: tp2 = e1->tp; ! 446: if(tp2->base == VEC) tp2->permanent = 1; ! 447: if (e1->base==ILIST) // PtoM ! 448: e1 = dummy; ! 449: else if (tp2 == char_type) // sizeof ('a') ! 450: e1 = dummy; ! 451: } ! 452: (void) tp2->tsizeof(); ! 453: tp = size_t_type; ! 454: return this; ! 455: ! 456: case CAST: ! 457: // return docast(tbl); ! 458: ! 459: { Pexpr ee = docast(tbl); ! 460: return ee->tp->is_ref() ? ee->contents() : ee; ! 461: } ! 462: ! 463: ! 464: case VALUE: ! 465: if ( tp2->base == COBJ || tp2->base == EOBJ) { ! 466: char *s = Pbase(tp2)->b_name->string; ! 467: //Pname tn = gtbl->look( s, 0 ); ! 468: //??? non type name apparently takes precedence ! 469: // Don't use global ftn if it hides local ! 470: // class ctor. (Note: More info is needed ! 471: // to detect all cases.) ! 472: Pname tn = tbl->look( s, 0 ); ! 473: //error( 'd', "tn: %n %t lex_levels: %d %d", tn, tn?tn->tp:0, tn?tn->lex_level:0, Pbase(tp2)->b_name->lex_level ); ! 474: if ( tn && tn->n_qualifier == 0 ! 475: && tn->lex_level == Pbase(tp2)->b_name->lex_level ! 476: && (tn->tp->base==FCT || tn->tp->base==OVERLOAD)) ! 477: { ! 478: Pexpr et = new expr( CALL, tn, e1 ); ! 479: *this = *et; ! 480: b = CALL; ! 481: break; ! 482: } ! 483: } ! 484: return dovalue(tbl); ! 485: ! 486: case NEW: ! 487: case GNEW: ! 488: return donew(tbl); ! 489: ! 490: case DELETE: // delete e1 OR delete[e2] e1 ! 491: case GDELETE: ! 492: { int i; ! 493: if (e1->base == ADDROF) error('w',"delete &E"); ! 494: e1 = e1->typ(tbl); ! 495: i = e1->tp->num_ptr(DELETE); ! 496: if (i != 'P') error("nonP deleted"); ! 497: if (e2) { ! 498: e2 = e2->typ(tbl); ! 499: e2->tp->integral(DELETE); ! 500: } ! 501: tp = void_type; ! 502: return this; ! 503: } ! 504: ! 505: case ILIST: /* an ILIST is pointer to an ELIST */ ! 506: e1 = e1->typ(tbl); ! 507: tp = any_type; ! 508: return this; ! 509: ! 510: case ELIST: ! 511: { Pexpr e; ! 512: Pexpr ex; ! 513: ! 514: if (e1 == dummy && e2==0) { ! 515: error("emptyIrL"); ! 516: tp = any_type; ! 517: return this; ! 518: } ! 519: ! 520: for (e=this; e; e=ex) { ! 521: Pexpr ee = e->e1; ! 522: //error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0); ! 523: if (e->base != ELIST) error('i',"elist%k",e->base); ! 524: if (ex = e->e2) { /* look ahead for end of list */ ! 525: if (ee == dummy) error("EX in EL"); ! 526: if (ex->e1 == dummy && ex->e2 == 0) { ! 527: /* { ... , } */ ! 528: DEL(ex); ! 529: e->e2 = ex = 0; ! 530: } ! 531: } ! 532: e->e1 = ee->typ(tbl); ! 533: t = e->e1->tp; ! 534: if (t->base == FCT) { // yuk! ! 535: ee = new expr(G_ADDROF,0,e->e1); ! 536: e->e1 = ee->typ(tbl); ! 537: t = e->e1->tp; ! 538: } ! 539: } ! 540: tp = t; ! 541: return this; ! 542: } ! 543: ! 544: case DOT: ! 545: case REF: ! 546: { if (e2) { // *. or ->* ! 547: if (b == REF) b = base = REFMUL; ! 548: break; ! 549: } ! 550: ! 551: Pbase b; ! 552: ! 553: e1 = e1->typ(tbl); ! 554: t = e1->tp; ! 555: ! 556: // check that . (->) is applied to class object (pointer) ! 557: if (base == REF) { ! 558: xxx: ! 559: switch (t->base) { ! 560: case TYPE: ! 561: t = Pbase(t)->b_name->tp; ! 562: goto xxx; ! 563: case COBJ: ! 564: { Pname n = Pclass(Pbase(t)->b_name->tp)->has_oper(REF); ! 565: if (n) { ! 566: n->n_used += 2; ! 567: e1 = new call(new ref(DOT,e1,n),0); ! 568: return typ(tbl); ! 569: } ! 570: // no break; ! 571: } ! 572: default: ! 573: error("nonP ->%n",mem); ! 574: t = any_type; ! 575: // no break; ! 576: case ANY: ! 577: goto qqq; ! 578: case PTR: ! 579: case VEC: ! 580: b = Pbase(Pptr(t)->typ); ! 581: } ! 582: } ! 583: else { // base == DOT ! 584: qqq: ! 585: switch (t->base) { ! 586: case TYPE: t = Pbase(t)->b_name->tp; goto qqq; ! 587: default: error("nonO .%n",mem); t = any_type; ! 588: case ANY: ! 589: case COBJ: break; ! 590: } ! 591: //error('d',"dot %k",e1->base); ! 592: switch (e1->base) { ! 593: case QUEST: ! 594: case ASSIGN: ! 595: case INCR: ! 596: case DECR: ! 597: case ASPLUS: ! 598: case ASMINUS: ! 599: case ASMUL: ! 600: case ASDIV: ! 601: case ASMOD: ! 602: case ASAND: ! 603: case ASOR: ! 604: case ASER: ! 605: case ASLS: ! 606: case ASRS: ! 607: case CM: ! 608: case G_CM: ! 609: base = REF; ! 610: e1 = e1->address(); ! 611: break; ! 612: case CALL: ! 613: case G_CALL: ! 614: //error('d'," f(). %n mem->tp %t",e1->fct_name,mem->tp); ! 615: #ifdef FDOTRIGHT ! 616: // this rewrite is only necessary on machines with broken C compilers ! 617: // there seems to be a lot of those ! 618: // and for inlines (a,b).c ! 619: if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline) ! 620: #endif ! 621: { // f(). => (tmp=f(),&tmp)-> ! 622: Pname tmp = make_tmp('Q',e1->tp,tbl); ! 623: //error('d',"fdot2 %k",e1->base); ! 624: e1 = init_tmp(tmp,e1,tbl); ! 625: Pexpr aa = tmp->address(); ! 626: e1 = new expr(G_CM,e1,aa); ! 627: e1->tp = aa->tp; ! 628: base = REF; ! 629: break; ! 630: } ! 631: } ! 632: b = Pbase(t); ! 633: } ! 634: ! 635: xxxx: ! 636: switch (b->base) { ! 637: case TYPE: ! 638: b = Pbase(b->b_name->tp); ! 639: goto xxxx; ! 640: default: ! 641: error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem); ! 642: case ANY: ! 643: tp = any_type; ! 644: return this; ! 645: case COBJ: ! 646: { Pclass cl = Pclass(Pbase(b)->b_name->tp); ! 647: if (cl->c_body == 1) cl->dcl_print(0); ! 648: break; ! 649: } ! 650: } ! 651: ! 652: /* ! 653: x.m is not a const even if x is a const object, this case is handled ! 654: by lval() rejecting it ! 655: */ ! 656: ! 657: if (mem->tp) { ! 658: tp = mem->tp; ! 659: for (Pexpr ee = mem; ee->base==REF; ee = ee->e1) { ! 660: if (ee->e1 == cc->c_this) { // this-> => p-> ! 661: ee->e1 = e1; ! 662: ee->base = base; ! 663: return mem->tp->is_ref() ? mem->contents() : mem; ! 664: } ! 665: } ! 666: ! 667: // return tp->base==RPTR ? contents() : this; ! 668: return tp->is_ref() ? contents() : this; ! 669: } ! 670: ! 671: ! 672: Pname q = Pname(mem)->n_qualifier; ! 673: Pexpr e = find_name(Pname(mem),Pclass(b->b_name->tp),0,base,cc->nof); ! 674: if (q && (e->base==REF || e->base==DOT)) ! 675: Pname(e)->n_initializer = Pexpr(q); ! 676: //error('d',"e %k %t %n",e->base,e->tp,e->base==NAME?e:e->base==REF?e->mem:0); ! 677: ! 678: for (Pexpr ee = e; ee->base==REF; ee = ee->e1) { ! 679: if (ee->e1 == cc->c_this) { // this-> => p-> ! 680: ee->e1 = e1; ! 681: ee->base = base; ! 682: break; ! 683: } ! 684: } ! 685: ! 686: if (e->base == NAME) { ! 687: switch (e->tp->base) { ! 688: case FCT: ! 689: case OVERLOAD: ! 690: mem = e; ! 691: tp = e->tp; ! 692: e = this; ! 693: } ! 694: } ! 695: ! 696: // function or static member ! 697: return e->tp->is_ref() ? e->contents() : e; ! 698: } ! 699: ! 700: //?? case G_CALL: ! 701: case CALL: /* handle undefined function names */ ! 702: //error('d',"call %k %t %k",e1->base,e1->tp,e2?e2->base:0); ! 703: if (e1->base==NAME && e1->tp==0) { ! 704: Pname q = Pname(e1)->n_qualifier; ! 705: e1 = find_name(Pname(e1),cc->cot,tbl,CALL,cc->nof); ! 706: //error('d',"e1 %k %t %n",e1->base,e1->tp,e1->base==NAME?e1:e1->base==REF?e1->mem:0); ! 707: if (q && (e1->base==REF ||e1->base==DOT)) // suppress virtual call ! 708: e1->n_initializer = Pexpr(q); ! 709: } ! 710: ! 711: if (e1->base==NAME && Pname(e1)->n_xref) { ! 712: // fudge to handle X(X&) args ! 713: e1 = new expr(DEREF,e1,0); ! 714: e1->tp = e1->e1->tp; // !! ! 715: } ! 716: ! 717: switch (e1->base) { ! 718: case DOT: ! 719: /* ! 720: #ifdef FDOTRIGHT ! 721: { ! 722: //error('d',"fdot1 %k",e1->e1->base); ! 723: switch (e1->e1->base) { ! 724: case CALL: ! 725: case G_CALL: // f().g() => (tmp=f(),tmp.g()) ! 726: { Pexpr ee = e1->e1; ! 727: Pexpr ex = ee->typ(tbl); ! 728: Pname tmp = make_tmp('Q',ex->tp,tbl); ! 729: ex = init_tmp(tmp,ex,tbl); ! 730: ! 731: Pexpr ee2 = new expr(base,e1,e2); ! 732: e1->base = DOT; ! 733: e1->e1 = tmp; ! 734: ! 735: base = G_CM; ! 736: e1 = ex; ! 737: e2 = ee2; ! 738: ! 739: return typ(tbl); ! 740: } ! 741: } ! 742: break; ! 743: } ! 744: #endif ! 745: */ ! 746: case REF: // becomes ob.x::~x(0) or ! 747: if (e2==0 // becomes p->x::~x(0) ! 748: && Pref(e1)->mem ! 749: && Pref(e1)->mem->base==NAME ! 750: && Pname(Pref(e1)->mem)->n_oper==DTOR) { ! 751: e1 = e1->typ(tbl); ! 752: Pexpr ee = call_dtor(e1->e1,Pref(e1)->mem,0,e1->base,one); ! 753: ee->tp = void_type; ! 754: return ee; ! 755: } ! 756: } ! 757: break; ! 758: ! 759: case QUEST: ! 760: cond = cond->typ(tbl); ! 761: case ANDAND: ! 762: case OROR: ! 763: Ntmp = 0; ! 764: } ! 765: ! 766: if (e1) { ! 767: e1 = e1->typ(tbl); ! 768: if (e1->tp->is_ref()) e1 = e1->contents(); ! 769: t1 = e1->tp; ! 770: // if (t1->is_cl_obj()) t1->tsizeof(); ! 771: } ! 772: else ! 773: t1 = 0; ! 774: ! 775: if (e2) { ! 776: e2 = e2->typ(tbl); ! 777: if (e2->tp->is_ref()) e2 = e2->contents(); ! 778: t2 = e2->tp; ! 779: // if (t2->is_cl_obj()) t2->tsizeof(); ! 780: } ! 781: else ! 782: t2 = 0; ! 783: ! 784: // error('d',"b %k t1 %t t2 %t",b,t1,t2); ! 785: switch (b) { // filter out non-overloadable operators ! 786: default: ! 787: { ! 788: Pexpr x = try_to_overload(tbl); ! 789: if (x) { ! 790: if (b==INCR || b==DECR) { ! 791: Pexpr fe = x->e1->base==NAME?x->e1:x->e1->mem; ! 792: // by default, prefix version of operator is chosen ! 793: // t2 set ==> ++n, t1 set ==> n++ ! 794: if (fe->tp->base==OVERLOAD && t2==0 && t1) ! 795: x=make_postfix(x); ! 796: } ! 797: return x; ! 798: } ! 799: // if (x) return x; ! 800: // error('d',"e2: %t t2: %t", e2->tp, t2); ! 801: if (t2 && t1==0 && t2!=e2->tp) t2 = e2->tp; ! 802: } ! 803: case DOT: ! 804: case G_CM: ! 805: case G_ADDROF: ! 806: case G_CALL: ! 807: case QUEST: ! 808: break; ! 809: } ! 810: ! 811: switch (b) { ! 812: case QUEST: ! 813: case ANDAND: ! 814: case OROR: ! 815: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,b); ! 816: } ! 817: ! 818: t = (t1==0) ? t2 : (t2==0) ? t1 : 0; ! 819: // error('d', "expr::typ t %t", t ); ! 820: // error('d',"b2 %d %k",b,b); ! 821: switch (b) { /* are the operands of legal types */ ! 822: case REFMUL: ! 823: base = REF; ! 824: // no break; ! 825: case DOT: ! 826: { // a .* p => &a MEMPTR p => appropriate indirection ! 827: // to be considered: what happens if a .* expression ! 828: // is used except in a call/=? ! 829: Pexpr a = e1->typ(tbl); ! 830: Ptype at = a->tp; ! 831: if (base == DOT) { ! 832: a = a->address(); ! 833: at = at->addrof(); // beware of n_xref ! 834: } ! 835: ! 836: while (at->base == TYPE) at = Pbase(at)->b_name->tp; ! 837: Pname cn = Pptr(at)->typ->is_cl_obj(); ! 838: Pclass mm = cn ? Pclass(cn->tp) : 0; ! 839: ! 840: Pexpr p = e2->typ(tbl); ! 841: Ptype pt = p->tp; ! 842: Pname pcn = pt->is_cl_obj(); ! 843: ! 844: //error('d',"mm %t pt %t",mm,pt); ! 845: if (pcn) { ! 846: Pclass cl = Pclass(pcn->tp); ! 847: Pname found = 0; ! 848: for (Pname on=cl->conv; on; on=on->n_list) { ! 849: Pfct f = Pfct(on->tp); ! 850: Pptr frt = Pptr(f->returns); ! 851: while (frt->base == TYPE) frt = Pptr(Pbase(frt)->b_name->tp); ! 852: if (frt->base!=PTR || Pptr(frt)->memof==0) break; ! 853: if (Pptr(frt)->memof==mm || mm->has_base(Pptr(frt)->memof)) { ! 854: if (found) ! 855: error("two possible conversions forP toM: %n and %n",found,on); ! 856: else ! 857: found = on; ! 858: } ! 859: } ! 860: //error('d',"found %n",found); ! 861: if (found) { ! 862: p = new ref(DOT,p,found); ! 863: p = new call(p,0); ! 864: p = p->typ(tbl); ! 865: pt = p->tp; ! 866: } ! 867: ! 868: } ! 869: while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp; ! 870: if (pt->base!=PTR || Pptr(pt)->memof==0) { ! 871: error("P toMX in .*E: %t",pt); ! 872: tp = any_type; ! 873: base = DUMMY; ! 874: return this; ! 875: } ! 876: Pclass pm = Pptr(pt)->memof; ! 877: ! 878: // while (at->base == TYPE) at = Pbase(at)->b_name->tp; ! 879: // Pname cn = Pptr(at)->typ->is_cl_obj(); ! 880: // Pclass mm = cn ? Pclass(cn->tp) : 0; ! 881: //error('d',"mm %t %t %d %d",mm,pm,pm->baseof(mm),mm->has_base(pm)); ! 882: ! 883: // if (mm!=pm && pm->baseof(mm)==0 && mm->has_base(pm)==0) { ! 884: if (mm != pm) { ! 885: if (mm->has_base(pm) == 0) { ! 886: error("badOT in .*E: %t (%s*X)",a->tp,pm->string); ! 887: tp = any_type; ! 888: //return this; ! 889: } ! 890: a = new texpr(CAST,pm->this_type,a); ! 891: e1 = a = a->typ(tbl); ! 892: } ! 893: ! 894: Ptype tpx = Pptr(pt)->typ; ! 895: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 896: ! 897: if (tpx->base == FCT) { // a.*p => (&a MEMPTR p) ! 898: base = MEMPTR; ! 899: tp2 = mm; // keep the class for simpl.c ! 900: e1 = a; ! 901: e2 = p; ! 902: } ! 903: else { // a .* p => *(typeof(p))((char*)&a + (int)p-1) ! 904: a = new cast(Pchar_type,a); ! 905: p = new cast(int_type,p); ! 906: p = new expr(MINUS,p,one); ! 907: p->tp = int_type; ! 908: Pexpr pl = new expr(PLUS,a,p); ! 909: pl->tp = Pchar_type; ! 910: base = DEREF; ! 911: pt = new ptr(PTR,tpx); // need a T* not a T C::* ! 912: Pptr(pt)->rdo = Pptr(tpx)->rdo; ! 913: mpglob = pm; ! 914: // PERM(pt); ! 915: e1 = new cast(pt,pl); ! 916: e2 = 0; ! 917: } ! 918: tp = tpx; ! 919: return tp->is_ref() ? contents() : this; ! 920: } ! 921: ! 922: case G_CALL: ! 923: case CALL: ! 924: tp = call_fct(tbl); /* two calls of use() for e1's names */ ! 925: if (tp->is_ref()) return contents(); ! 926: return this; ! 927: ! 928: case DEREF: ! 929: if (e1 == dummy) error("O missing before []\n"); ! 930: if (e2 == dummy) error("subscriptE missing"); ! 931: ! 932: if (t) { /* *t */ ! 933: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 934: // t->vec_type(); ! 935: if (t->base==PTR && Pptr(t)->memof) error("P toM dereferenced"); ! 936: tp = t->deref(); ! 937: } ! 938: else { // e1[e2] that is *(e1+e2) ! 939: //error('d',"deref %t[%t]",t1,t2); ! 940: if (t1->vec_type()) { // e1[e2] ! 941: switch (t2->base) { ! 942: case CHAR: ! 943: case SHORT: ! 944: case INT: ! 945: case LONG: ! 946: case EOBJ: ! 947: break; ! 948: default: ! 949: { Pname cn = t2->is_cl_obj(); ! 950: if (cn) // conversion to integral? ! 951: e2 = check_cond(e2,DEREF,tbl); ! 952: else ! 953: t2->integral(DEREF); ! 954: } ! 955: } ! 956: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp; ! 957: if (t1->base==PTR && Pptr(t1)->memof) error("P toM dereferenced"); ! 958: tp = t1->deref(); ! 959: (void) tp->tsizeof(); ! 960: } ! 961: else if (t2->vec_type()) { // really e2[e1] ! 962: t1->integral(DEREF); ! 963: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp; ! 964: if (t2->base==PTR && Pptr(t2)->memof) error("P toM dereferenced"); ! 965: tp = t2->deref(); ! 966: (void) tp->tsizeof(); ! 967: } ! 968: else { ! 969: error("[] applied to nonPT:%t[%t]",t1,t2); ! 970: tp = any_type; ! 971: } ! 972: } ! 973: ! 974: if (tp->is_ref()) return contents(); ! 975: ! 976: return this; ! 977: ! 978: case G_ADDROF: ! 979: case ADDROF: ! 980: //error('d',"addrof(%d) %k %d",base,e2->base,e2->base); ! 981: switch (e2->base) { // potential lvalues ! 982: case G_CM: ! 983: if (base==ADDROF && e2->e2->base==NAME) { ! 984: // check for cfront generated result variable ! 985: char* s = e2->e2->string; ! 986: if (s[0]=='_' && s[1] && s[1]=='_') { ! 987: if (s[2] && (s[2]=='R' || s[2]=='V')) { ! 988: error("address of non-lvalue"); ! 989: break; ! 990: } ! 991: } ! 992: } ! 993: case CM: // &(a,b) => (a,&b) ! 994: { ! 995: Pexpr ee = e2; ! 996: ee->tp = 0; ! 997: ee->e2 = new expr(base,0,ee->e2); ! 998: delete this; ! 999: return ee->typ(tbl); ! 1000: } ! 1001: case QUEST: // & (a?b:c) => (a?&b:&c) ! 1002: { ! 1003: Pexpr ee = e2; ! 1004: ee->tp = 0; ! 1005: ee->e1 = new expr(base,0,ee->e1); ! 1006: ee->e2 = new expr(base,0,ee->e2); ! 1007: delete this; ! 1008: return ee->typ(tbl); ! 1009: } ! 1010: case INCR: ! 1011: case DECR: ! 1012: if (e2->e1) break; ! 1013: case ASSIGN: ! 1014: case ASPLUS: ! 1015: case ASMINUS: ! 1016: case ASMUL: ! 1017: case ASDIV: ! 1018: case ASMOD: ! 1019: case ASAND: ! 1020: case ASOR: ! 1021: case ASER: ! 1022: case ASLS: ! 1023: case ASRS: ! 1024: return e2->address(); ! 1025: } ! 1026: ! 1027: if (e2->lval(ADDROF) == 0) { ! 1028: if (error_count) { // error_count == 0 possible ! 1029: // in case of & const ! 1030: tp = any_type; ! 1031: return this; ! 1032: } ! 1033: } ! 1034: ! 1035: tp = t->addrof(); ! 1036: ! 1037: if( base==ADDROF && mpglob) ! 1038: Pptr(tp)->memof = mpglob; ! 1039: ! 1040: if (e2->tp->base == VEC) { ! 1041: if(e2->base != NAME) { ! 1042: base = CAST; ! 1043: tp2 = tp; ! 1044: e1 = e2; ! 1045: e2 = 0; ! 1046: return this; ! 1047: } ! 1048: } ! 1049: ! 1050: // tp = t->addrof(); ! 1051: ! 1052: if (t->base==FCT) ! 1053: Pptr(tp)->memof = Pfct(t)->memof; ! 1054: ! 1055: // if (t->tconst() && vec_const==0 && fct_const==0) Pptr(tp)->rdo = 1; ! 1056: // ??? & (const T) is NOT T*const but const T* ! 1057: ! 1058: switch (e2->base) { ! 1059: case NAME: ! 1060: mname: // check for &s::i ! 1061: { Pname n2 = Pname(e2); ! 1062: Pname cn = (n2->n_table && n2->n_table!=gtbl) ? n2->n_table->t_name : 0; ! 1063: // error('d',"n2 %k cn %n t %t",n2->base,cn,t); ! 1064: if (cn == 0) break; ! 1065: // Pptr(tp)->memof = Pclass(cn->tp); ! 1066: ! 1067: if (t->base==FCT && Pfct(t)->f_this==0) { ! 1068: Pptr(tp)->memof = 0; ! 1069: break; ! 1070: } ! 1071: ! 1072: switch (t->base) { ! 1073: case OVERLOAD: ! 1074: return e2; ! 1075: case FCT: ! 1076: // error('d', "cn->tp: %d, %k", cn->tp, cn->tp->base); ! 1077: Pptr(tp)->memof = Pclass(cn->tp); //SSS ! 1078: ! 1079: if (Pfct(t)->f_virtual) { ! 1080: // { 0,vtbl index,0 } ! 1081: e1 = new ival(Pfct(t)->f_virtual); ! 1082: e1 = new expr(ELIST,zero,e1); ! 1083: e2 = zero; ! 1084: base = ILIST; ! 1085: // tp = int_type; ! 1086: return this; ! 1087: } // use the pointer ! 1088: ! 1089: // { 0,-1,(int(*)())ptr } ! 1090: e1 = new ival(-1); ! 1091: e1 = new expr(ELIST,zero,e1); ! 1092: // e2 is the name ! 1093: e2 = new cast(Pfct_type,e2); ! 1094: base = ILIST; ! 1095: // tp = int_type; ! 1096: return this; ! 1097: ! 1098: // return e2; ! 1099: ! 1100: default: ! 1101: if (n2->n_stclass != STATIC) { // offset + 1 ! 1102: //error('d',"n2 %n %d",n2,n2->n_offset); ! 1103: //error('d',"q %n cn %n",n2->n_qualifier,cn); ! 1104: e1 = new ival(n2->n_offset+1); ! 1105: Pptr(tp)->memof = Pclass(cn->tp); ! 1106: //error('d',"cl %d %s i %d",Pclass(cn->tp),Pclass(cn->tp)?Pclass(cn->tp)->string:"0",n2->n_offset); ! 1107: } ! 1108: else ! 1109: return this; ! 1110: } ! 1111: //error('d',"int_type"); ! 1112: e1->tp = int_type; ! 1113: e2 = 0; ! 1114: tp2 = tp; ! 1115: base = CAST; ! 1116: return this; ! 1117: } ! 1118: case DOT: ! 1119: case REF: ! 1120: { ! 1121: Pname m = Pname(e2->mem); ! 1122: // error( 'd', "e2->mem->base: %k", e2->mem->base ); ! 1123: // Pname m = (e2->mem->base == MDOT) ? Pname(e2->mem->mem) : Pname(e2->mem); ! 1124: while ( m->base == MDOT ) m = Pname(Pexpr(m)->mem); ! 1125: ! 1126: Pfct f = Pfct(m->tp); ! 1127: ! 1128: if (f->base == FCT || f->base == OVERLOAD) { // &p->f ! 1129: Pexpr q = Pname(e2)->n_initializer; // &p->x::f ! 1130: ! 1131: if (q && bound==0 && e2->e1==cc->c_this) { ! 1132: // FUDGE: &this->x::f => &x::f ! 1133: DEL(e2); ! 1134: e2 = m; ! 1135: goto mname; ! 1136: } ! 1137: ! 1138: bound = 1; ! 1139: if(!f->f_static) { ! 1140: error(strict_opt?0:'w', ! 1141: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)", ! 1142: m->n_table->t_name->string, ! 1143: m->n_table->t_name->string, ! 1144: m->string ! 1145: ); ! 1146: } ! 1147: ! 1148: if (q || f->f_virtual==0) { ! 1149: // & x.f => & f ! 1150: DEL(e2); ! 1151: e2 = m; ! 1152: } ! 1153: } ! 1154: break; ! 1155: ! 1156: } ! 1157: case MEMPTR: ! 1158: // &(p->*q) ! 1159: error("& .* E"); ! 1160: } ! 1161: ! 1162: return this; ! 1163: ! 1164: case UMINUS: ! 1165: t->numeric(UMINUS); ! 1166: tp = t; ! 1167: return this; ! 1168: ! 1169: case UPLUS: ! 1170: t->num_ptr(UPLUS); ! 1171: tp = t; ! 1172: if (ansi_opt==0) { ! 1173: base = PLUS; ! 1174: e1 = zero; ! 1175: } ! 1176: return this; ! 1177: ! 1178: case NOT: ! 1179: e2 = check_cond(e2,NOT,tbl); ! 1180: tp = int_type; ! 1181: return this; ! 1182: ! 1183: case COMPL: ! 1184: t->integral(COMPL); ! 1185: tp = t; ! 1186: return this; ! 1187: ! 1188: case INCR: ! 1189: case DECR: ! 1190: { ! 1191: // error('d',"incr-decr: e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0); ! 1192: Pexpr e = e1?e1:e2; // e1!=0 ==> e++ or e-- ! 1193: // e1==0 ==> ++e or --e ! 1194: ! 1195: e->lval(b); ! 1196: ! 1197: switch(e->base) { ! 1198: case QUEST: ! 1199: e->tp=0; ! 1200: e->e1 = e1 ? new expr(base,e->e1,0) : new expr(base,0,e->e1); ! 1201: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2); ! 1202: delete this; ! 1203: return e->typ(tbl); ! 1204: case CM: ! 1205: case G_CM: ! 1206: e->tp=0; ! 1207: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2); ! 1208: delete this; ! 1209: return e->typ(tbl); ! 1210: case INCR: ! 1211: case DECR: ! 1212: if(e->e1) ! 1213: break; ! 1214: nin++; ! 1215: if(e->e2->not_simple()) ! 1216: error('s',"overly complex %k of %k",b,e->base); ! 1217: nin--; ! 1218: e = new expr(G_CM,e,e->e2->typ(tbl)); ! 1219: if (e1) e1=e; else e2=e; ! 1220: // e1?e1:e2 = e; ! 1221: return typ(tbl); ! 1222: case ASSIGN: ! 1223: case ASPLUS: ! 1224: case ASMINUS: ! 1225: case ASMUL: ! 1226: case ASDIV: ! 1227: case ASMOD: ! 1228: case ASAND: ! 1229: case ASOR: ! 1230: case ASER: ! 1231: case ASLS: ! 1232: case ASRS: ! 1233: nin++; ! 1234: if(e->e1->not_simple()) ! 1235: error('s',"overly complex %k of %k",b,e->base); ! 1236: nin--; ! 1237: e = new expr(G_CM,e,e->e1->typ(tbl)); ! 1238: if (e1) e1=e; else e2=e; ! 1239: // e1?e1:e2 = e; ! 1240: return typ(tbl); ! 1241: } ! 1242: } ! 1243: ! 1244: r1 = t->num_ptr(b); ! 1245: if (r1='P' && t->check(Pvoid_type,0)==0) error("%k of void*",b); ! 1246: tp = t; ! 1247: return this; ! 1248: ! 1249: } ! 1250: ! 1251: if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b); ! 1252: switch (b) { ! 1253: case MUL: ! 1254: case DIV: ! 1255: r1 = t1->numeric(b); ! 1256: r2 = t2->numeric(b); ! 1257: nppromote(b); ! 1258: break; ! 1259: ! 1260: case PLUS: ! 1261: r2 = t2->num_ptr(PLUS); ! 1262: r1 = t1->num_ptr(PLUS); ! 1263: nppromote(PLUS); ! 1264: goto void_check; ! 1265: ! 1266: case MINUS: ! 1267: r2 = t2->num_ptr(MINUS); ! 1268: r1 = t1->num_ptr(MINUS); ! 1269: if (r2=='P' && r1!='P' && r1!='A') error("nonP - P"); ! 1270: nppromote(MINUS); ! 1271: void_check: ! 1272: if ((r1='P' && t1->check(Pvoid_type,0)==0) ! 1273: || (r2='P' && t2->check(Pvoid_type,0)==0)) ! 1274: error("%k of void*",b); ! 1275: tp = t; ! 1276: break; ! 1277: ! 1278: case LS: ! 1279: case RS: ! 1280: case AND: ! 1281: case OR: ! 1282: case ER: ! 1283: switch (e1->base) { ! 1284: case LT: ! 1285: case LE: ! 1286: case GT: ! 1287: case GE: ! 1288: case EQ: ! 1289: case NE: ! 1290: error('w',"%kE as operand for%k",e1->base,b); ! 1291: } ! 1292: switch (e2->base) { ! 1293: case LT: ! 1294: case LE: ! 1295: case GT: ! 1296: case GE: ! 1297: case EQ: ! 1298: case NE: ! 1299: error('w',"%kE as operand for%k",e2->base,b); ! 1300: } ! 1301: case MOD: ! 1302: r1 = t1->integral(b); ! 1303: r2 = t2->integral(b); ! 1304: nppromote(b); ! 1305: break; ! 1306: ! 1307: case LT: ! 1308: case LE: ! 1309: case GT: ! 1310: case GE: ! 1311: case EQ: ! 1312: case NE: ! 1313: r1 = t1->num_ptr(b); ! 1314: r2 = t2->num_ptr(b); ! 1315: if (r1=='P' && r2=='I') { // allow things like: ! 1316: // if (p==2-2) ! 1317: // YUCK! ! 1318: Neval = 0; ! 1319: long i = e2->eval(); ! 1320: if (Neval==0 && i==0) { ! 1321: DEL(e2); ! 1322: e2 = zero; ! 1323: r2 = 'Z'; ! 1324: } ! 1325: } ! 1326: else if (r2=='P' && r1=='I') { ! 1327: Neval = 0; ! 1328: long i = e1->eval(); ! 1329: if (Neval==0 && i==0) { ! 1330: DEL(e1); ! 1331: e1 = zero; ! 1332: r1 = 'Z'; ! 1333: } ! 1334: } ! 1335: ! 1336: if (b!=EQ && b!=NE) { ! 1337: if (r1=='P' && r2=='Z') error("P%k 0",b); ! 1338: if (r2=='P' && r1=='Z') error("P%k 0",b); ! 1339: } ! 1340: ! 1341: // make sure functions are properly converted to pointers to ! 1342: // functions and make sure overloaded functions are rejected ! 1343: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl); ! 1344: if (r1 == FCT) e1 = ptof(0,e1,tbl); ! 1345: if (r2 == FCT) e2 = ptof(0,e2,tbl); ! 1346: ! 1347: npcheck(b); ! 1348: ! 1349: if (r1=='P') { // need cast for pointers to virtual and second bases ! 1350: Pptr p1 = t1->is_ptr(); ! 1351: Pptr p2 = t2->is_ptr(); ! 1352: Pname cn = p1?p1->typ->is_cl_obj():0; ! 1353: Pname cn2 = p2?p2->typ->is_cl_obj():0; ! 1354: ! 1355: if (cn && cn2) { ! 1356: Pclass cl = Pclass(cn->tp); ! 1357: Pclass cl2 = Pclass(cn2->tp); ! 1358: ! 1359: if (cl->has_base(cl2)) { ! 1360: e1 = cast_cptr(cl2,e1,tbl,0); ! 1361: e1 = new cast(p2,e1); ! 1362: } ! 1363: else if (cl2->has_base(cl)) { ! 1364: e2 = cast_cptr(cl,e2,tbl,0); ! 1365: e2 = new cast(p1,e2); ! 1366: } ! 1367: } ! 1368: } ! 1369: ! 1370: if (r1=='P' && t1->memptr()) { ! 1371: mpmp: ! 1372: if (r2=='Z') { ! 1373: e2 = zero; ! 1374: e1 = new mdot("i",e1); ! 1375: e1->i1 = 9; ! 1376: } ! 1377: else if (r2=='P' && t2->memptr()) { ! 1378: // ERROR: no check for sideeffects ! 1379: Pexpr i1 = new mdot("i",e1); ! 1380: Pexpr i2; ! 1381: i1->i1 = 9; ! 1382: ! 1383: i2 = e2; ! 1384: while ( i2->base == CAST ) ! 1385: i2 = i2->e1; ! 1386: if ( i2->base == ILIST ) ! 1387: e2 = i2; ! 1388: ! 1389: if (e2->base==ILIST) ! 1390: i2 = e2->e1->e2; ! 1391: else { ! 1392: i2 = new mdot("i",e2); ! 1393: i2->i1 = 9; ! 1394: } ! 1395: ! 1396: Pexpr f1 = new mdot("f",e1); ! 1397: Pexpr f2; ! 1398: f1->i1 = 9; ! 1399: if (e2->base == ILIST) ! 1400: // f2 = new cast(Pfct_type,e2->e2); ! 1401: f2 = e2->e2; ! 1402: else { ! 1403: f2 = new mdot("f",e2); ! 1404: f2->i1 = 9; ! 1405: } ! 1406: ! 1407: Pexpr ei = new expr(base,i1,i2); ! 1408: Pexpr fi = new expr(base,f1,f2); ! 1409: ! 1410: base = ANDAND; ! 1411: e1 = ei; ! 1412: e2 = fi; ! 1413: } else if (r2=='P') { ! 1414: error('s',"%t %k %t",t1,base,t2); ! 1415: } ! 1416: } ! 1417: else if (r2=='P' && t2->memptr()) { ! 1418: Pexpr ee = e1; // swap ! 1419: e1 = e2; ! 1420: e2 = ee; ! 1421: int rr = r1; ! 1422: r1 = r2; ! 1423: r2 = rr; ! 1424: Ptype tt = t1; ! 1425: t1 = t2; ! 1426: t2 = tt; ! 1427: goto mpmp; ! 1428: } ! 1429: t = int_type; ! 1430: break; ! 1431: ! 1432: case ANDAND: ! 1433: case OROR: ! 1434: e1 = check_cond(e1,b,tbl); ! 1435: e2 = check_cond(e2,b,tbl); ! 1436: t = int_type; ! 1437: break; ! 1438: ! 1439: case QUEST: ! 1440: { ! 1441: Pname c1, c2; ! 1442: cond = check_cond(cond,b,tbl); ! 1443: //error('d',"cond %k %t",cond->base,cond->tp); ! 1444: //error('d',"t1 %t t2 %t",t1,t2); ! 1445: ! 1446: // still doesn't do complete checking for possible conversions... ! 1447: ! 1448: bit MPTR = 0; // local hack ! 1449: ! 1450: extern int suppress_error; // global hack ! 1451: suppress_error++; ! 1452: r1 = t1->num_ptr(b); ! 1453: r2 = t2->num_ptr(b); ! 1454: suppress_error--; ! 1455: if (r1=='P' && r2=='P' && t1->memptr() && t2->memptr()) { ! 1456: ! 1457: ++MPTR; // prevent later sorry ! 1458: ! 1459: // watch for casts ! 1460: Pexpr tt = e1; ! 1461: while ( tt->base == CAST ) tt = tt->e1; ! 1462: if ( tt->base == ILIST ) e1 = tt; ! 1463: ! 1464: tt = e2; ! 1465: while ( tt->base == CAST ) tt = tt->e1; ! 1466: if ( tt->base == ILIST ) e2 = tt; ! 1467: ! 1468: // cannot have sides return (expr?{}:{}) ! 1469: // reuse same temp for both sides ?: ! 1470: Pname temp = make_tmp( 'A', mptr_type, tbl ); ! 1471: ! 1472: e1 = mptr_assign( temp, e1 ); ! 1473: e1 = new expr( G_CM, e1, temp ); ! 1474: e1->tp = temp->tp; ! 1475: ! 1476: e2 = mptr_assign( temp, e2 ); ! 1477: e2 = new expr( G_CM, e2, temp ); ! 1478: e2->tp = temp->tp; ! 1479: } ! 1480: ! 1481: if (t1==t2 ! 1482: || ( (c1=t1->is_cl_obj()) ! 1483: && (c2=t2->is_cl_obj()) ! 1484: && (c1->tp==c2->tp) ! 1485: )) ! 1486: t = t1; ! 1487: else { ! 1488: r1 = t1->num_ptr(b); ! 1489: r2 = t2->num_ptr(b); ! 1490: ! 1491: if (r1=='P' && r2=='P') { ! 1492: Pptr p1 = t1->is_ptr(); ! 1493: Pptr p2 = t2->is_ptr(); ! 1494: //error('d',"p1 %t p2 %t",p1,p2); ! 1495: if ((c1 = p1->typ->is_cl_obj()) ! 1496: && (c2 = p2->typ->is_cl_obj())) { ! 1497: Pclass cl1 = Pclass(c1->tp); ! 1498: Pclass cl2 = Pclass(c2->tp); ! 1499: if (cl1==cl2 || cl2->has_base(cl1)) { ! 1500: t = t1; ! 1501: goto caca; ! 1502: } ! 1503: else if (cl1->has_base(cl2)) { ! 1504: t = t2; ! 1505: goto caca; ! 1506: } ! 1507: } ! 1508: } ! 1509: ! 1510: if (r1==FCT && r2==FCT) { // fudge ! 1511: if (t1->check(t2,ASSIGN)) ! 1512: error("badTs in ?:E: %t and %t",t1,t2); ! 1513: else if (Pfct(t1)->memof) error('s',"conditionalE with%t",t1); ! 1514: t = t1; ! 1515: } ! 1516: else ! 1517: nppromote(b); ! 1518: caca: ! 1519: //error('d',"?: t %t t1 %t t2 %t",t,t1,t2); ! 1520: if (t!=t1 && t->check(t1,0)) { ! 1521: PERM(t); ! 1522: e1 = new cast(t,e1); ! 1523: } ! 1524: ! 1525: if (t!=t2 && t->check(t2,0)) { ! 1526: PERM(t); ! 1527: e2 = new cast(t,e2); ! 1528: } ! 1529: ! 1530: Pptr pt = t->is_ptr(); ! 1531: //if (pt && pt->base==PTR && pt->memof) error('s',"conditionalE with%t",t); ! 1532: if (pt && pt->base==PTR && pt->memof && MPTR == 0) error('s',"conditionalE with%t",t); ! 1533: } ! 1534: } ! 1535: break; ! 1536: ! 1537: case ASPLUS: ! 1538: r1 = t1->num_ptr(ASPLUS); ! 1539: r2 = t2->num_ptr(ASPLUS); ! 1540: nppromote(ASPLUS); ! 1541: goto ass; ! 1542: ! 1543: case ASMINUS: ! 1544: r1 = t1->num_ptr(ASMINUS); ! 1545: r2 = t2->num_ptr(ASMINUS); ! 1546: if (r2=='P' && r1!='P' && r1!='A') error("P -= nonP"); ! 1547: nppromote(ASMINUS); ! 1548: goto ass; ! 1549: ! 1550: case ASMUL: ! 1551: case ASDIV: ! 1552: r1 = t1->numeric(b); ! 1553: r2 = t1->numeric(b); ! 1554: nppromote(b); ! 1555: goto ass; ! 1556: ! 1557: case ASMOD: ! 1558: r1 = t1->integral(ASMOD); ! 1559: r2 = t2->integral(ASMOD); ! 1560: nppromote(ASMOD); ! 1561: goto ass; ! 1562: ! 1563: case ASAND: ! 1564: case ASOR: ! 1565: case ASER: ! 1566: case ASLS: ! 1567: case ASRS: ! 1568: r1 = t1->integral(b); ! 1569: r2 = t2->integral(b); ! 1570: npcheck(b); ! 1571: t = int_type; ! 1572: goto ass; ! 1573: ass: ! 1574: if (r1='P' && t1->check(Pvoid_type,0)==0) error("%k of void*",b); ! 1575: tp = t; ! 1576: as_type = t; /* the type of the rhs */ ! 1577: t2 = t; ! 1578: ! 1579: case ASSIGN: ! 1580: //error('d',"assign %k: %t %t %s",b,t1,t2,ignore_const?"ignore const":""); ! 1581: //error('d'," e1 %d %k e1 %d %k",e1,e1->base,e2,e2->base); ! 1582: if (ignore_const) { // handle static initializers ! 1583: // represented as assignments ! 1584: // ignore consts. ! 1585: tp = e1->tp; ! 1586: return this; ! 1587: } ! 1588: ! 1589: switch (e1->base) { ! 1590: case G_CM: ! 1591: case CM: // (a,b)=c => *(a,&b)=c ! 1592: { ! 1593: e1->e2 = new expr(G_ADDROF,0,e1->e2); ! 1594: e1->tp = 0; ! 1595: e1 = new expr(DEREF,e1,0); ! 1596: return typ(tbl); ! 1597: } ! 1598: case QUEST: // (a?b:c)=d => *(a?&b:&c)=c ! 1599: { ! 1600: e1->e1 = new expr(G_ADDROF,0,e1->e1); ! 1601: e1->e2 = new expr(G_ADDROF,0,e1->e2); ! 1602: e1->tp = 0; ! 1603: e1 = new expr(DEREF,e1,0); ! 1604: return typ(tbl); ! 1605: } ! 1606: case ASSIGN: // (a*=b)=c => a*=b,a=c ! 1607: case ASPLUS: ! 1608: case ASMINUS: ! 1609: case ASMUL: ! 1610: case ASDIV: ! 1611: case ASMOD: ! 1612: case ASAND: ! 1613: case ASOR: ! 1614: case ASER: ! 1615: case ASLS: ! 1616: case ASRS: ! 1617: { ! 1618: base = G_CM; ! 1619: nin++; ! 1620: if (e1->e1->not_simple()) error('s',"lvalue %k too complicated",b); ! 1621: nin--; ! 1622: Pexpr aa = new expr(e1->base,e1->e1,e1->e2); ! 1623: Pexpr bb = new expr(b,e1->e1,e2); ! 1624: e1 = aa; ! 1625: e2 = bb; ! 1626: return typ(tbl); ! 1627: } ! 1628: case INCR: ! 1629: case DECR: // ++a=b => ++a,a=b ! 1630: { ! 1631: if(!e1->e2) break ; ! 1632: base = G_CM; ! 1633: nin++; ! 1634: if (e1->e2->not_simple()) error('s',"lvalue %k too complicated",b); ! 1635: nin--; ! 1636: Pexpr aa = new expr(e1->base,0,e1->e2); ! 1637: Pexpr bb = new expr(b,e1->e2,e2); ! 1638: e1 = aa; ! 1639: e2 = bb; ! 1640: return typ(tbl); ! 1641: } ! 1642: case REF: ! 1643: { ! 1644: Pexpr r = e1; ! 1645: // hack to prevent ! 1646: // f().i = j ! 1647: // transformed into ! 1648: // ((t=f()),&t)->i = j ! 1649: if (r->e1->base==G_CM ! 1650: && r->e1->e2->base==G_ADDROF ! 1651: && r->e1->e2->e2->base==NAME) { ! 1652: char* s = r->e1->e2->e2->string; ! 1653: if (s[0]=='_' && s[1]=='_') ! 1654: error("left hand side not lvalue"); ! 1655: } ! 1656: } ! 1657: } ! 1658: ! 1659: if (e1->lval(b) == 0) { ! 1660: tp = any_type; ! 1661: return this; ! 1662: } ! 1663: lkj: ! 1664: switch (t1->base) { ! 1665: case TYPE: ! 1666: t1 = Pbase(t1)->b_name->tp; ! 1667: goto lkj; ! 1668: case INT: ! 1669: case CHAR: ! 1670: case SHORT: ! 1671: // if (e2->base==ICON && e2->tp==long_type) ! 1672: // error('w',"long constant assigned to%k",t1->base); ! 1673: { Ptype t = e2->tp; ! 1674: csi: ! 1675: switch (t->base) { ! 1676: case TYPE: ! 1677: t = Pbase(t)->b_name->tp; goto csi; ! 1678: case LONG: ! 1679: case FLOAT: ! 1680: case DOUBLE: ! 1681: case LDOUBLE: ! 1682: error('w',"%t assigned to %t",e2->tp,t1); ! 1683: } ! 1684: } ! 1685: // no break ! 1686: case LONG: ! 1687: if (b==ASSIGN ! 1688: && Pbase(t1)->b_unsigned ! 1689: && e2->base==UMINUS ! 1690: && e2->e2->base==ICON) ! 1691: error('w',"negative assigned to unsigned"); ! 1692: break; ! 1693: case PTR: ! 1694: if (b == ASSIGN) { ! 1695: //error('d',"ptr t1 %t %d %t",t1,t1->memptr(),t2); ! 1696: //?? if (t1->memptr() && t2->base!=OVERLOAD) break; ! 1697: e2 = ptr_init(Pptr(t1),e2,tbl); ! 1698: t2 = e2->tp; ! 1699: //error('d',"pchecked %d",Pchecked); ! 1700: if (Pchecked) { ! 1701: tp = e1->tp; ! 1702: return this; ! 1703: } ! 1704: } ! 1705: break; ! 1706: case COBJ: ! 1707: { Pname c1 = t1->is_cl_obj(); ! 1708: // test of c1->tp necessary for ``fake classes'' ! 1709: // _Sdd generated for vector assignemnts ! 1710: if (c1 ! 1711: && c1->tp ! 1712: /* && Pclass(c1->tp)->memtbl->look("__as",0)==0*/) { ! 1713: //&& Pclass(c1->tp)->has_oper(ASSIGN)==0) { ! 1714: Pname c2 = t2->is_cl_obj(); ! 1715: // error('d', "expr::typ: c1: %n c2: %n", c1, c2 ); ! 1716: if (c1 != c2) { ! 1717: /* ! 1718: consider: ! 1719: ! 1720: struct A { A(B&); }; ! 1721: struct B : A {}; ! 1722: ! 1723: A aa; ! 1724: B bb; ! 1725: ! 1726: aa = bb; // aa.operator=(A(bb)); ! 1727: // optimize to aa.A(bb) when possible ! 1728: // avoid temporary where aa = *(A*)&bb is legal ! 1729: */ ! 1730: // error('d',"expr::typ c1 %n %d c2 %n %d",c1,c1?c1->tp:0,c2,c2?c2->tp:0); ! 1731: if (c2 ! 1732: && c2->tp ! 1733: && can_coerce(t1,t2)==0 ! 1734: //&& Pclass(c2->tp)->has_base(Pclass(c1->tp)) ! 1735: //&& (1<is_unique_base(Pclass(c2->tp),c1->string,0)) ! 1736: && (vcllist->clear(),vcllist=0,1<is_unique_base(Pclass(c2->tp),c1->string,0)) ! 1737: && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 1738: // error('d',"aaa"); ! 1739: if (make_assignment(c1)) return try_to_overload(tbl); ! 1740: } ! 1741: // optimize ! 1742: else { ! 1743: e2 = new expr(ELIST,e2,0); ! 1744: e2 = new texpr(VALUE,t1,e2); ! 1745: if (Pclass(c1->tp)->has_dtor()==0 && ! 1746: Pclass(c1->tp)->has_oper(ASSIGN)==0) { ! 1747: // optimize ! 1748: // error('d',"bbb"); ! 1749: e2->e2 = e1; ! 1750: e2 = e2->typ(tbl); ! 1751: if (e2->base==DEREF && e2->e1->base==G_CALL || ! 1752: e2->base==ASSIGN && e2->e1==e1) { ! 1753: // error('d',"ccc"); ! 1754: *this = *e2; ! 1755: } ! 1756: tp = t1; ! 1757: return this; ! 1758: } ! 1759: return typ(tbl); ! 1760: } ! 1761: } ! 1762: // test of c1->tp necessary for ``fake classes'' ! 1763: // _Sdd generated for vector assignemnts ! 1764: else if (c1->tp && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 1765: if (make_assignment(c1)) return try_to_overload(tbl); ! 1766: } ! 1767: } ! 1768: (void) t1->tsizeof(); ! 1769: break; ! 1770: } ! 1771: } ! 1772: ! 1773: //error('d',"check(%t,%t) -> %d",e1->tp,t2,try_to_coerce(t1,e2,"assignment",tbl)); ! 1774: { Pexpr x = try_to_coerce(t1,e2,"assignment",tbl); ! 1775: if (x) ! 1776: e2 = x; ! 1777: else if (e1->tp->check(t2,ASSIGN)) ! 1778: error("bad assignmentT:%t =%t",e1->tp,t2); ! 1779: else if ((t1 = t1->is_ptr()) && t1->memptr()) { ! 1780: if (t2 == zero_type) { ! 1781: Pexpr ee = new expr(ELIST,zero,zero); ! 1782: e2 = new expr(ILIST,ee,zero); ! 1783: } ! 1784: else if (t2->base==PTR && t2->memptr()) { ! 1785: // do nothing: structure assignment ! 1786: } ! 1787: else { ! 1788: Pexpr x = ptr_init(Pptr(t1),e2,tbl); ! 1789: if (x != e2) e2 = x; ! 1790: } ! 1791: } ! 1792: } ! 1793: t = e1->tp; // the type of the lhs ! 1794: break; ! 1795: case CM: ! 1796: case G_CM: ! 1797: t = t2; ! 1798: break; ! 1799: default: ! 1800: error('i',"unknown operator%k",b); ! 1801: } ! 1802: ! 1803: tp = t; ! 1804: return this; ! 1805: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.