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