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