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