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