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