|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/expr2.c 1.1.5.29" */ ! 2: /*************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All rigths Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: expr2.c: ! 11: ! 12: type check expressions ! 13: ! 14: ************************************************************************/ ! 15: ! 16: #include "cfront.h" ! 17: #include "size.h" ! 18: ! 19: void name::assign() ! 20: { ! 21: if (n_assigned_to++ == 0) { ! 22: switch (n_scope) { ! 23: case FCT: ! 24: if (n_used && n_addr_taken==0) { ! 25: Ptype t = tp; ! 26: ll: ! 27: switch (t->base) { ! 28: case TYPE: ! 29: t=Pbase(t)->b_name->tp; goto ll; ! 30: case VEC: ! 31: break; ! 32: default: ! 33: if (curr_loop) ! 34: error('w',&where,"%n may have been used before set",this); ! 35: else ! 36: error('w',&where,"%n used before set",this); ! 37: } ! 38: } ! 39: } ! 40: } ! 41: } ! 42: ! 43: int ignore_const; // for use by ref_init ! 44: static is_dataMemPtr(Pexpr); ! 45: ! 46: int expr::lval(TOK oper) ! 47: { ! 48: register Pexpr ee = this; ! 49: register Pname n; ! 50: int deref = 0; ! 51: char* es; ! 52: char * con_idx; ! 53: int tpconst; ! 54: ! 55: //error('d',"%k expr::lval %k",base,oper); ! 56: ! 57: tpconst = tp->tconst (); ! 58: con_idx = "constant"; ! 59: ! 60: switch (oper) { ! 61: case ADDROF: ! 62: case G_ADDROF: es = "address of"; break; ! 63: case DEREF: es = "dereference of"; break; ! 64: case INCR: es = "increment of"; goto def; ! 65: case DECR: es = "decrement of"; goto def; ! 66: default: es = "assignment to"; ! 67: def: ! 68: if (ignore_const==0 && tpconst) { ! 69: tp->tconst(); /* set globals */ ! 70: if (oper) { ! 71: if (base == NAME) /* can't be indexable */ { ! 72: if (vec_const && Pname(this)->n_scope==ARG) ! 73: break; ! 74: error("%s constant%n",es,this); ! 75: } ! 76: else ! 77: error("%s %s",es, con_idx); ! 78: } ! 79: return 0; ! 80: } ! 81: } ! 82: ! 83: for(;;) { ! 84: //error('d',"loop %k",ee->base); ! 85: switch (ee->base) { ! 86: // case G_CALL: ! 87: // case CALL: ! 88: default: ! 89: defa: ! 90: if (deref == 0) { ! 91: if (oper) error("%s%k (not an lvalue)",es,ee->base); ! 92: return 0; ! 93: } ! 94: return 1; ! 95: case ZERO: ! 96: case CCON: ! 97: case ICON: ! 98: case FCON: ! 99: if (oper) error("%s numeric constant",es); ! 100: return 0; ! 101: case STRING: ! 102: if (oper) error('w',"%s string constant",es); ! 103: return 1; ! 104: case CAST: ! 105: switch( oper ) { ! 106: case 0: ! 107: case ADDROF: ! 108: case G_ADDROF: ! 109: case DEREF: ! 110: goto defa; ! 111: default: ! 112: if ( ee->tp->base == PTR ! 113: && is_dataMemPtr(ee) ) ! 114: { // check for const class object ! 115: /* This probable wants to be removed for the ! 116: same reason that the code below under DOT and REF ! 117: was removed -- it dosen't respect ignore_const. --benson */ ! 118: ! 119: Pexpr te; ! 120: te = ee->e1->e1->e1; ! 121: if ( te->base == G_ADDROF ) ! 122: te = te->e2; ! 123: if ( te->base == NAME ) { ! 124: Ptype pt = te->tp; ! 125: if ( pt->base == PTR ) ! 126: pt = Pptr(pt)->typ; ! 127: if ( pt->tconst() ) ! 128: error("%sCMP of const%n",es,te); ! 129: return 0; ! 130: } ! 131: } ! 132: goto defa; ! 133: } ! 134: ! 135: case DEREF: ! 136: { ! 137: Pexpr ee1 = ee->e1; ! 138: // error( 'd', "ee1: %k", ee1->base ); ! 139: switch (ee1->base) { // *& vanishes ! 140: case ADDROF: // *& ! 141: return 1; ! 142: case G_CM: ! 143: case CM: // look for *(a,&b) ! 144: if (ee1->e2->base==G_ADDROF ! 145: || ee1->e2->base==ADDROF) ! 146: return 1; ! 147: goto defaa; ! 148: case QUEST: // look for *(q?&a:&b) ! 149: if ((ee1->e1->base==G_ADDROF ! 150: || ee1->e1->base==ADDROF) ! 151: && (ee1->e2->base==G_ADDROF ! 152: || ee1->e2->base==ADDROF)) ! 153: return 1; ! 154: // no break ! 155: default: ! 156: defaa: ! 157: ee = ee1; ! 158: deref = 1; ! 159: } ! 160: break; ! 161: } ! 162: ! 163: case QUEST: ! 164: { int x1 = ee->e1->lval(deref?0:oper); ! 165: int x2 = ee->e2->lval(deref?0:oper); ! 166: if (ee->e1->tp->check(ee->e2->tp,0)) return 0; ! 167: if (deref) return 1; ! 168: return x1 && x2; ! 169: } ! 170: ! 171: case INCR: ! 172: case DECR: ! 173: if (e1) goto defa; // postfix does not preserve lval ! 174: case ASSIGN: ! 175: case ASPLUS: ! 176: case ASMINUS: ! 177: case ASMUL: ! 178: case ASDIV: ! 179: case ASMOD: ! 180: case ASAND: ! 181: case ASOR: ! 182: case ASER: ! 183: case ASLS: ! 184: case ASRS: ! 185: return 1; ! 186: ! 187: case CM: ! 188: case G_CM: ! 189: if (ee->e2->lval(deref?0:oper)==0) return deref; ! 190: return 1; ! 191: ! 192: case MEMPTR: ! 193: ee = ee->e2; ! 194: break; ! 195: ! 196: case MDOT: ! 197: ee = ee->mem; ! 198: break; ! 199: ! 200: case DOT: ! 201: //error('d',"dot %k oper %k",ee->e1->base,oper); ! 202: switch (ee->e1->base) { // update use counts, etc. ! 203: case NAME: ! 204: switch (oper) { ! 205: case ADDROF: ! 206: case G_ADDROF: Pname(ee->e1)->take_addr(); ! 207: case 0: break; ! 208: case ASSIGN: Pname(ee->e1)->n_used--; ! 209: default: Pname(ee->e1)->assign(); // asop ! 210: } ! 211: break; ! 212: case DOT: ! 213: Pexpr e = ee->e1; ! 214: do e=e->e1; while (e->base==DOT); ! 215: if (e->base == NAME) { ! 216: switch (oper) { ! 217: case ADDROF: ! 218: case G_ADDROF: Pname(e)->take_addr(); ! 219: case 0: break; ! 220: case ASSIGN: Pname(e)->n_used--; ! 221: default: Pname(e)->assign(); // asop ! 222: } ! 223: } ! 224: } ! 225: ! 226: n = Pname(ee->mem); ! 227: while (n->base == MDOT) n = Pname(Pref(n)->mem); ! 228: ! 229: #if 0 ! 230: /* This code is no longer needed now that const is propagated up the ! 231: tree bottom up by expr::typ and co-conspirators. --benson ! 232: Since it don't respect ignore_const, it causes bizarre behavior ! 233: (which ought to be demonstable with the AT&T version, but ! 234: tends not to be because tname stripping hides consts that this ! 235: would find. --benson */ ! 236: if (deref==0 && ee->e1->tp->tconst()) { ! 237: switch (oper) { ! 238: case 0: ! 239: case ADDROF: ! 240: case G_ADDROF: ! 241: case DEREF: ! 242: break; ! 243: default: ! 244: error("%sM%n of%t",es,n,ee->e1->tp); ! 245: } ! 246: return 0; ! 247: } ! 248: #endif ! 249: goto xx; ! 250: ! 251: case REF: ! 252: n = Pname(ee->mem); ! 253: while (n->base == MDOT) n = Pname(Pref(n)->mem); ! 254: ! 255: if (deref==0 && ee->e1) { //BR ! 256: Ptype p = ee->e1->tp; ! 257: zxc: ! 258: switch (p->base) { ! 259: case TYPE: p = Pbase(p)->b_name->tp; goto zxc; ! 260: case PTR: ! 261: case VEC: break; ! 262: default: error('i',"expr::lval %t->%n",p,n); ! 263: } ! 264: #if 0 ! 265: /* This code is no longer needed now that const is propagated up the ! 266: tree bottom up by expr::typ and co-conspirators. --benson ! 267: Since it don't respect ignore_const, it causes bizarre behavior ! 268: (which ought to be demonstable with the AT&T version, but ! 269: tends not to be because tname stripping hides consts that this ! 270: would find. --benson */ ! 271: if (Pptr(p)->typ->tconst()) { ! 272: switch (oper) { ! 273: case 0: ! 274: case ADDROF: ! 275: case G_ADDROF: ! 276: case DEREF: ! 277: break; ! 278: default: ! 279: error("%sM%n of%t",es,n,Pptr(p)->typ); ! 280: } ! 281: return 0; ! 282: } ! 283: #endif ! 284: } ! 285: goto xx; ! 286: ! 287: case NAME: ! 288: n = Pname(ee); ! 289: xx: ! 290: // error('d',"name xx: %n oper %d lex_level: %d",n,oper,n->lex_level); ! 291: if (deref || oper==0) return 1; ! 292: ! 293: if (n->tp->base==FIELD && Pbase(n->tp)->b_bits==0) { ! 294: error("%s 0-length field%n",es,n); ! 295: return 0; ! 296: } ! 297: ! 298: switch (oper) { ! 299: case ADDROF: ! 300: case G_ADDROF: ! 301: { Pfct f = (Pfct)n->tp; ! 302: ! 303: if (n->n_sto == REGISTER) { ! 304: if (warning_opt) error('w',"& register%n",n); ! 305: // return 0; ! 306: n->n_sto = 0; ! 307: n->n_stclass = AUTO; ! 308: } ! 309: ! 310: if (f == 0) { ! 311: error("& label%n",n); ! 312: return 0; ! 313: } ! 314: ! 315: if (n->n_stclass == ENUM) { ! 316: error("& enumerator%n",n); ! 317: return 0; ! 318: } ! 319: ! 320: if (n->tp->base == FIELD) { ! 321: error("& field%n",n); ! 322: return 0; ! 323: } ! 324: ! 325: n->n_used--; ! 326: if (n->n_qualifier) // oops, not the real one ! 327: n = Pclass(n->n_table->t_name->tp)->memtbl->look(n->string,0); ! 328: n->take_addr(); ! 329: ! 330: // suppress hoisting of local consts ! 331: int statmem = n->n_scope==0 || n->n_scope==PUBLIC || n->n_scope == FCT; ! 332: if (n->n_evaluated && n->n_scope!=ARG) { // &const ! 333: n->n_evaluated = 0; // use allocated version ! 334: n->n_initializer = new ival(n->n_val); ! 335: if (statmem == 0) n->dcl_print(0); ! 336: } ! 337: else if (f->base==FCT && n->n_dcl_printed==0) ! 338: n->dcl_print(0); ! 339: break; ! 340: } ! 341: ! 342: case ASSIGN: ! 343: //error('d',"ass %n %d",n,n->n_used); ! 344: n->n_used--; ! 345: n->assign(); ! 346: break; ! 347: // goto check_void; ! 348: default: /* incr ops, and asops */ ! 349: if (cc->tot && n==cc->c_this) { ! 350: error("%n%k",n,oper); ! 351: return 0; ! 352: } ! 353: // check_void: ! 354: // { Ptype t = n->tp; ! 355: // while (t->base==TYPE) t = Pbase(t)->b_name->tp; ! 356: // if (t==Pvoid_type) { ! 357: // error("%s%t",es,n->tp); ! 358: // return 0; ! 359: // } ! 360: // } ! 361: n->assign(); ! 362: } ! 363: return 1; ! 364: } ! 365: } ! 366: } ! 367: ! 368: int char_to_int(char* s) ! 369: /* assume s points to a string: ! 370: 'c' ! 371: or '\c' ! 372: or '\0' ! 373: or '\ddd' ! 374: or multi-character versions of the above ! 375: (hex constants have been converted to octal by the parser) ! 376: */ ! 377: { ! 378: register int i = 0; ! 379: register char c, d, e; ! 380: ! 381: switch (*s) { ! 382: default: ! 383: error('i',"char constant store corrupted"); ! 384: case '`': ! 385: error("bcd constant"); ! 386: return 0; ! 387: case '\'': ! 388: break; ! 389: } ! 390: ! 391: for(;;) /* also handle multi-character constants */ ! 392: switch (c = *++s) { ! 393: case '\'': ! 394: return i; ! 395: case '\\': /* special character */ ! 396: switch (c = *++s) { ! 397: case '0': case '1': case '2': case '3': case '4': ! 398: case '5': case '6': case '7': /* octal representation */ ! 399: c -= '0'; ! 400: switch (d = *++s) { /* try for 2 */ ! 401: ! 402: case '0': case '1': case '2': case '3': case '4': ! 403: case '5': case '6': case '7': ! 404: d -= '0'; ! 405: switch (e = *++s) { /* try for 3 */ ! 406: ! 407: case '0': case '1': case '2': case '3': case '4': ! 408: case '5': case '6': case '7': ! 409: c = c*64+d*8+e-'0'; ! 410: break; ! 411: default: ! 412: c = c*8+d; ! 413: s--; ! 414: } ! 415: break; ! 416: default: ! 417: s--; ! 418: } ! 419: break; ! 420: case 'b': ! 421: c = '\b'; ! 422: break; ! 423: case 'f': ! 424: c = '\f'; ! 425: break; ! 426: case 'n': ! 427: c = '\n'; ! 428: break; ! 429: case 'r': ! 430: c = '\r'; ! 431: break; ! 432: case 't': ! 433: c = '\t'; ! 434: break; ! 435: case '\\': ! 436: c = '\\'; ! 437: break; ! 438: case '\'': ! 439: c = '\''; ! 440: break; ! 441: } ! 442: /* no break */ ! 443: default: ! 444: if (i) i <<= BI_IN_BYTE; ! 445: i += c; ! 446: } ! 447: } ! 448: ! 449: const A10 = 'A'-10; ! 450: const a10 = 'a'-10; ! 451: ! 452: long str_to_long(register const char* p) ! 453: { ! 454: register c; ! 455: register unsigned long i= 0; ! 456: const char* pp = p; ! 457: ! 458: // error( 'd', "str_to_long: %s", p ); ! 459: ! 460: if ((c=*p++) == '0') { ! 461: switch (c = *p++) { ! 462: case 0: ! 463: return 0; ! 464: ! 465: case 'l': ! 466: case 'L': /* long zero */ ! 467: return 0; ! 468: ! 469: case 'x': ! 470: case 'X': /* hexadecimal */ ! 471: while (c=*p++) { ! 472: switch (c) { ! 473: case 'l': ! 474: case 'L': ! 475: case 'U': ! 476: case 'u': ! 477: return i; ! 478: case 'A': ! 479: case 'B': ! 480: case 'C': ! 481: case 'D': ! 482: case 'E': ! 483: case 'F': ! 484: i = i*16 + c-A10; ! 485: break; ! 486: case 'a': ! 487: case 'b': ! 488: case 'c': ! 489: case 'd': ! 490: case 'e': ! 491: case 'f': ! 492: i = i*16 + c-a10; ! 493: break; ! 494: default: ! 495: i = i*16 + c-'0'; ! 496: } ! 497: } ! 498: return i; ! 499: ! 500: default: /* octal */ ! 501: do ! 502: switch (c) { ! 503: case 'l': ! 504: case 'L': ! 505: case 'U': ! 506: case 'u': ! 507: return i; ! 508: default: ! 509: i = i*8 + c-'0'; ! 510: } ! 511: while (c=*p++); ! 512: return i; ! 513: } ! 514: } ! 515: /* decimal */ ! 516: i = c-'0'; ! 517: while (c=*p++) ! 518: switch (c) { ! 519: case 'l': ! 520: case 'L': ! 521: case 'U': ! 522: case 'u': ! 523: return i; ! 524: default: ! 525: { unsigned long ii = i; ! 526: i = i*10 + c-'0'; ! 527: if (i<ii) goto bad; ! 528: } ! 529: } ! 530: return i; ! 531: bad: ! 532: error("integer constant %s larger that the largest long",pp); ! 533: return i; ! 534: ! 535: ! 536: } ! 537: ! 538: bit type::is_unsigned() ! 539: { ! 540: Ptype t = this; ! 541: while (t->base==TYPE) t = Pbase(t)->b_name->tp; ! 542: if (t->base == PTR) return 0; ! 543: return Pbase(t)->b_unsigned; ! 544: } ! 545: ! 546: char* Neval; ! 547: bit binary_val; ! 548: ! 549: unsigned long expr::ueval(long x1, long x2) ! 550: { ! 551: unsigned long i1 = (unsigned long) x1; ! 552: unsigned long i2 = (unsigned long) x2; ! 553: //error('d',"ueval %k %ld %ld",base,x1,x2); ! 554: switch (base) { ! 555: case UMINUS: return -i2; ! 556: case UPLUS: return i2; ! 557: case NOT: return !i2; ! 558: case COMPL: return ~i2; ! 559: case CAST: return i1; ! 560: case PLUS: return i1+i2; ! 561: case MINUS: return i1-i2; ! 562: case MUL: return i1*i2; ! 563: case LS: return i1<<i2; ! 564: case RS: return i1>>i2; ! 565: case NE: return i1!=i2; ! 566: case EQ: return i1==i2; ! 567: case LT: return i1<i2; ! 568: case LE: return i1<=i2; ! 569: case GT: return i1>i2; ! 570: case GE: return i1>=i2; ! 571: case AND: return i1&i2; ! 572: case ANDAND: return i1&&i2; ! 573: case OR: return i1|i2; ! 574: case OROR: return i1||i2; ! 575: case ER: return i1^i2; ! 576: case MOD: return (i2==0) ? 1 : i1%i2; ! 577: case QUEST: return (cond->eval()) ? i1 : i2; ! 578: case DIV: if (i2 == 0) { ! 579: if (Neval == 0) { ! 580: Neval = "divide by zero"; ! 581: error('w',"divide by zero"); ! 582: } ! 583: return 1; ! 584: } ! 585: return i1/i2; ! 586: case CM: ! 587: case G_CM: ! 588: return i2; ! 589: } ! 590: ! 591: Neval = "unsigned expression"; ! 592: return 0; ! 593: } ! 594: ! 595: long expr::eval() ! 596: { ! 597: static long cast_mask[] = { 0377, 0177777, 077777777, ~0 }; ! 598: ! 599: if (Neval) return 1; ! 600: // error('d',"eval %k",base); ! 601: ! 602: switch (base) { ! 603: case ZERO: return 0; ! 604: case IVAL: return i1; ! 605: case ICON: return str_to_long(string); ! 606: case CCON: return char_to_int(string); ! 607: case FCON: Neval = "float in constant expression"; return 1; ! 608: case STRING: Neval = "string in constant expression"; return 1; ! 609: case EOBJ: return Pname(this)->n_val; ! 610: case SIZEOF: ! 611: extern no_sizeof; ! 612: if (no_sizeof) Neval = "sizeof"; ! 613: return tp2->tsizeof(); ! 614: ! 615: case NAME: ! 616: { Pname n = Pname(this); ! 617: // error('d',"eval %n eval %d %d",n,n->n_evaluated,n->n_val); ! 618: // error('d',"eval tp->tconst() %d, n->n_initializer: %k", n->tp->tconst(), n->n_initializer?n->n_initializer->base:0 ); ! 619: if (n->n_evaluated && n->n_scope!=ARG) return n->n_val; ! 620: if (n->n_initializer ! 621: && n->n_scope!=ARG ! 622: && n->n_initializer->base==IVAL // encoding for outlined ! 623: && n->n_initializer->i1==n->n_val // const see ::lval above ! 624: && n->tp->tconst()) return n->n_val; ! 625: if (binary_val && strcmp(string,"_result")==0) return 8888; ! 626: Neval = "cannot evaluate constant"; ! 627: return 1; ! 628: } ! 629: case ICALL: ! 630: if (e1) { ! 631: il->i_next = curr_icall; ! 632: curr_icall = il; ! 633: long i = e1->eval(); ! 634: curr_icall = il->i_next; ! 635: return i; ! 636: } ! 637: Neval = "void inlineF"; ! 638: return 1; ! 639: case ANAME: ! 640: { Pname n = (Pname)this; ! 641: int argno = (int)n->n_val; ! 642: Pin il; ! 643: for (il=curr_icall; il; il=il->i_next) ! 644: if (il->i_table == n->n_table) goto aok; ! 645: goto bok; ! 646: aok: ! 647: if (il->i_args[argno].local) { ! 648: bok: ! 649: Neval = "inlineF call too complicated for constant expression"; ! 650: return 1; ! 651: } ! 652: Pexpr aa = il->i_args[argno].arg; ! 653: return aa->eval(); ! 654: } ! 655: case CAST: ! 656: { if (e1->base == FCON) { ! 657: char* p = e1->string; ! 658: while (*p!='.') p++; ! 659: if (p==e1->string) *p++ = '0'; ! 660: *p = 0; ! 661: e1->base = ICON; ! 662: } ! 663: long i = e1->eval(); ! 664: Ptype tt = tp2; ! 665: strip: ! 666: switch (tt->base) { ! 667: default: ! 668: Neval = "cast to non-integral type in constant expression"; ! 669: break; ! 670: case TYPE: ! 671: tt = Pbase(tt)->b_name->tp; ! 672: goto strip; ! 673: case EOBJ: ! 674: case LONG: ! 675: case INT: ! 676: case CHAR: ! 677: case SHORT: ! 678: { ! 679: if (BI_IN_BYTE!=8) error('i',"expr::eval() assumes 8 bit bytes, please re-write it"); ! 680: if (4<SZ_LONG) error('i',"expr::eval() assumes sizeof(long)<=4, please re-write it"); ! 681: i &= cast_mask[tp2->tsizeof()-1]; ! 682: } ! 683: } ! 684: return i; ! 685: } ! 686: case UMINUS: ! 687: case UPLUS: ! 688: case NOT: ! 689: case COMPL: ! 690: case PLUS: ! 691: case MINUS: ! 692: case MUL: ! 693: case LS: ! 694: case RS: ! 695: case NE: ! 696: case LT: ! 697: case LE: ! 698: case GT: ! 699: case GE: ! 700: case AND: ! 701: case OR: ! 702: case ER: ! 703: case DIV: ! 704: case MOD: ! 705: case QUEST: ! 706: case EQ: ! 707: case ANDAND: ! 708: break; ! 709: case OROR: ! 710: if (binary_val) { // a||b, don't evaluate b if a!=0 ! 711: long i1 = (e1) ? e1->eval() : 0; ! 712: if (Neval==0 && i1 && e1->tp->is_unsigned()==0) return i1; ! 713: } ! 714: break; ! 715: case CM: ! 716: case G_CM: ! 717: break; ! 718: case G_ADDROF: ! 719: case ADDROF: ! 720: if (binary_val) { // beware of &*(T*)0 ! 721: switch (e2->base) { ! 722: case NAME: ! 723: case DOT: ! 724: case REF: return 9999; ! 725: } ! 726: } ! 727: default: ! 728: Neval = "bad operator in constant expression"; ! 729: return 1; ! 730: } ! 731: ! 732: long i1 = (e1) ? e1->eval() : 0; ! 733: long i2 = (e2) ? e2->eval() : 0; ! 734: ! 735: if (binary_val && i1==9999 && i2==9999) { ! 736: Neval = ""; ! 737: return 1; ! 738: } ! 739: ! 740: if (Neval==0 ! 741: && ((e1&&e1->tp->is_unsigned()) || (e2&&e2->tp->is_unsigned()))) ! 742: return (long) ueval(i1,i2); ! 743: ! 744: switch (base) { ! 745: case UMINUS: return -i2; ! 746: case UPLUS: return i2; ! 747: case NOT: return !i2; ! 748: case COMPL: return ~i2; ! 749: case CAST: return i1; ! 750: case PLUS: return i1+i2; ! 751: case MINUS: return i1-i2; ! 752: case MUL: return i1*i2; ! 753: case LS: return i1<<i2; ! 754: case RS: return i1>>i2; ! 755: case NE: return i1!=i2; ! 756: case EQ: return i1==i2; ! 757: case LT: return i1<i2; ! 758: case LE: return i1<=i2; ! 759: case GT: return i1>i2; ! 760: case GE: return i1>=i2; ! 761: case AND: return i1&i2; ! 762: case ANDAND: return i1&&i2; ! 763: case OR: return i1|i2; ! 764: case OROR: return i1||i2; ! 765: case ER: return i1^i2; ! 766: case MOD: return (i2==0) ? 1 : i1%i2; ! 767: case QUEST: return (cond->eval()) ? i1 : i2; ! 768: case DIV: if (i2 == 0) { ! 769: if (Neval == 0) { ! 770: Neval = "divide by zero"; ! 771: error('w',"divide by zero"); ! 772: } ! 773: return 1; ! 774: } ! 775: return i1/i2; ! 776: case CM: ! 777: case G_CM: ! 778: return i2; ! 779: } ! 780: } ! 781: extern TOK ppbase; ! 782: bit classdef::baseof(Pname f) ! 783: /* ! 784: is ``this'' class a public base class of "f"'s class ! 785: or its immediate base class ! 786: */ ! 787: { ! 788: Ptable ctbl = f->n_table; ! 789: Pname b = ctbl->t_name; ! 790: ! 791: if (b == 0) return 0; ! 792: Pclass cl = Pclass(b->tp); ! 793: if (cl == 0) return 0; ! 794: if (cl == this) return 1; ! 795: ppbase = PUBLIC; ! 796: Pclass bcl = is_base(cl->string); ! 797: return (bcl && ppbase==PUBLIC); ! 798: } ! 799: ! 800: bit classdef::baseof(Pclass cl) ! 801: /* ! 802: is ``this'' class a public base class of "cl" ! 803: */ ! 804: { ! 805: if (cl == 0) return 0; ! 806: if (cl == this) return 1; ! 807: ppbase = PUBLIC; ! 808: Pclass bcl = is_base(cl->string); ! 809: return (bcl && ppbase==PUBLIC); ! 810: } ! 811: ! 812: static int mem_match(Pfct f1, Pfct f2) ! 813: /* ! 814: check class membership. ! 815: ! 816: For some reason checking f_this==0 works and f_static doesn't ! 817: */ ! 818: { ! 819: // if (f1->memof) return f2->f_this ?f2->memof==f1->memof : 0; ! 820: // if (f1 && f1->memof) return f2->f_this?f2->memof==f1->memof : 0; ! 821: // return f2->f_this==0; ! 822: if (f1==0 || f2==0) return 0; ! 823: if (f1->memof && f2->f_this && f2->memof!=f1->memof) return 0; ! 824: if (f2->f_this) return 0; ! 825: if (f1->check(f2,ASSIGN)) return 0; ! 826: return 1; ! 827: } ! 828: ! 829: int Pchecked; ! 830: ! 831: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl) ! 832: /* ! 833: a kludge: initialize/assign-to pointer to function ! 834: */ ! 835: { ! 836: Pfct f; ! 837: Pname n = 0; ! 838: eee: ! 839: //error('d',"ptof %t %t %k",ef,e->tp,e->base); ! 840: switch (e->base) { ! 841: case QUEST: ! 842: e->e1 = ptof(ef,e->e1,tbl); ! 843: e->e2 = ptof(ef,e->e2,tbl); ! 844: return e; ! 845: case CM: ! 846: case G_CM: ! 847: e->e2 = ptof(ef,e->e2,tbl); ! 848: return e; ! 849: case NAME: ! 850: f = Pfct(e->tp); ! 851: // n = Pname(e); ! 852: ! 853: switch (f->base) { ! 854: case OVERLOAD: ! 855: e = Pgen(f)->find(ef,0); ! 856: if (e == 0) error("cannot deduceT for &overloaded%n",e); ! 857: // e = n; ! 858: // no break ! 859: case FCT: ! 860: Pchecked = mem_match(ef,Pfct(e->tp)); ! 861: e = new expr(G_ADDROF,0,e); ! 862: return e->typ(tbl); // handle &B::f ! 863: //e->tp = f; ! 864: } ! 865: goto ad; ! 866: ! 867: case ZERO: ! 868: if (ef->memof) { ! 869: e = new expr(ELIST,zero,zero); ! 870: e = new expr(ILIST,e,zero); ! 871: e->tp = zero_type; ! 872: return e; ! 873: } ! 874: break; ! 875: ! 876: case MDOT: ! 877: error('s',"P toM of not firstB"); ! 878: do e = e->mem; while (e->base == MDOT); ! 879: goto eee; ! 880: ! 881: case DOT: ! 882: case REF: ! 883: f = Pfct(e->mem->tp); ! 884: ! 885: switch (f->base) { ! 886: case OVERLOAD: ! 887: e = Pgen(f)->find(ef,0); ! 888: if (n == 0) error("cannot deduceT for &overloaded%n",e->mem); ! 889: // e->mem = n; ! 890: // no break ! 891: case FCT: ! 892: Pchecked = mem_match(ef,Pfct(e->tp)); ! 893: e = new expr(G_ADDROF,0,e); ! 894: return e->typ(tbl); // handle &B::f ! 895: // n = Pname(e->mem); ! 896: // e = n->address(); ! 897: } ! 898: goto ad; ! 899: ! 900: case ADDROF: ! 901: case G_ADDROF: ! 902: f = Pfct(e->e2->tp); ! 903: ad: ! 904: if (f->base == OVERLOAD) { ! 905: n = Pgen(f)->find(ef,0); ! 906: if (n == 0) error("cannot deduceT for &overloaded %s()",Pgen(f)->fct_list->f->string); ! 907: Pchecked = mem_match(ef,Pfct(n->tp)); ! 908: e->e2 = n; ! 909: e->tp = n->tp; ! 910: } ! 911: if (n) n->lval(ADDROF); ! 912: break; ! 913: ! 914: case CAST: ! 915: { ! 916: Pexpr te = e->e1; ! 917: if (e->e1->base == G_ADDROF) te = e->e1->e2; ! 918: (void) ptof(ef,te,tbl); ! 919: } ! 920: } ! 921: return e; ! 922: } ! 923: ! 924: Pexpr ptr_init(Pptr p, Pexpr init, Ptable tbl) ! 925: /* ! 926: check for silly initializers ! 927: ! 928: char* p = 0L; ?? fudge to allow redundant and incorrect `L' ! 929: char* p = 2 - 2; ?? worse ! 930: */ ! 931: { ! 932: //error('d',"ptr_init: p=%t init->tp=%t init->base %k",p,init->tp,init->base); ! 933: ! 934: Pchecked = 0; ! 935: ! 936: Ptype it = init->tp; ! 937: itl: ! 938: switch (it->base) { ! 939: case TYPE: ! 940: it = Pbase(it)->b_name->tp; goto itl; ! 941: case ZTYPE: ! 942: // if (init == zero) break; ! 943: break; ! 944: case EOBJ: ! 945: case INT: ! 946: case CHAR: ! 947: case SHORT: ! 948: { Neval = 0; ! 949: long i = init->eval(); ! 950: if (Neval) ! 951: error("badPIr: %s",Neval); ! 952: else ! 953: if (i) ! 954: error("badPIr value %d",i); ! 955: else { ! 956: DEL(init); ! 957: init = zero; ! 958: } ! 959: break; ! 960: } ! 961: case LONG: ! 962: if (init->base==ICON ! 963: && init->string[0]=='0' ! 964: && (init->string[1]=='L' || init->string[1]=='l')) { ! 965: DEL(init); ! 966: init = zero; ! 967: } ! 968: break; ! 969: } ! 970: ! 971: Pclass c1 = p->memof; ! 972: ! 973: if (c1) { ! 974: //error('d',"c1 %t",c1); ! 975: if (init==zero) ! 976: ; ! 977: else { ! 978: Pclass c2; ! 979: //error('d',"it %t %d",it,it->base); ! 980: switch (it->base) { ! 981: case FCT: ! 982: c2 = Pfct(it)->memof; ! 983: break; ! 984: case OVERLOAD: ! 985: c2 = Pfct(Pgen(it)->fct_list->f->tp)->memof; ! 986: break; ! 987: case PTR: ! 988: case RPTR: ! 989: c2 = Pptr(it)->memof; ! 990: break; ! 991: default: ! 992: c2 = 0; ! 993: } ! 994: ! 995: if (c2 == 0) { ! 996: // initialization by &A::f ! 997: //error('d',"curious"); ! 998: } ! 999: else if (c1 != c2) { ! 1000: Nptr = 0; ! 1001: Noffset = 0; ! 1002: vcllist->clear(); ! 1003: vcllist=0; ! 1004: int u1 = is_unique_base(c1,c2->string,0); ! 1005: //error('d',"c1 %t c2 %t u1 %d off %d",c1,c2,u1,Noffset); ! 1006: if (u1 && (Nptr || Noffset)) { ! 1007: // requires offset manipulation ! 1008: int bad = 0; ! 1009: if (u1 == 1 && !Nptr) { ! 1010: //error('d',"try c1 %t c2 %t u1 %d off %d",c1,c2,u1,Noffset); ! 1011: //error('d',"init %k %t",init->base,init->tp); ! 1012: if (init->base==ILIST) { ! 1013: // d = d+Noffset; ! 1014: //error('d'," d %k %d",init->e1->e1->base,init->e1->e1->i1); ! 1015: switch (init->e1->e1->base) { ! 1016: case IVAL: ! 1017: init->e1->e1->i1 += Noffset; ! 1018: break; ! 1019: case ZERO: ! 1020: init->e1->e1 = new ival(Noffset); ! 1021: break; ! 1022: default: ! 1023: bad = 1; ! 1024: } ! 1025: ! 1026: //error('d'," i %k %d",init->e1->e2->base,init->e1->e2->i1); ! 1027: // if (i<0) f = vptroffset ! 1028: switch (init->e1->e2->base) { ! 1029: case IVAL: ! 1030: if (0<init->e1->e2->i1) { ! 1031: //error('d',"vptr"); ! 1032: extern Ptype Pfct_type; ! 1033: // store vptr offset ! 1034: // init->e2 = new cast(Pfct_type,zero); ! 1035: } ! 1036: else ! 1037: break; ! 1038: default: ! 1039: bad = 1; ! 1040: } ! 1041: } ! 1042: else ! 1043: bad = 1; ! 1044: ! 1045: } ! 1046: else ! 1047: bad = 1; ! 1048: ! 1049: if (bad) error('s',"%t assigned to %t (too complicated)",init->tp,p); ! 1050: } ! 1051: ! 1052: Nptr = 0; ! 1053: Noffset = 0; ! 1054: vcllist->clear(); ! 1055: vcllist=0; ! 1056: int u2 = is_unique_base(c2,c1->string,0); ! 1057: //error('d',"c1 %t c2 %t u2 %d off %d",c1,c2,u2,Noffset); ! 1058: if (u2 && (Nptr || Noffset)) { ! 1059: // requires offset manipulation ! 1060: error('s',"%t assigned to %t",init->tp,p); ! 1061: } ! 1062: } ! 1063: } ! 1064: } ! 1065: ! 1066: Ptype pit = p->typ; ! 1067: lll: ! 1068: //error('d',"p %t pit %t",p,pit); ! 1069: switch (pit->base) { ! 1070: case TYPE: ! 1071: pit = Pbase(pit)->b_name->tp; ! 1072: goto lll; ! 1073: case FCT: ! 1074: return ptof(Pfct(pit),init,tbl); ! 1075: case COBJ: ! 1076: { Pptr r; ! 1077: //error('d',"cobj: ptr %t, ref %t",it->is_ptr(),it->is_ref()); ! 1078: if (r=it->is_ptr_or_ref()) { ! 1079: Pchecked = 1; ! 1080: TOK b = p->base; // could be REF ! 1081: TOK bb = r->base; ! 1082: if (b==RPTR) p->base = PTR; ! 1083: if (bb==RPTR) r->base = PTR; ! 1084: if (p->check(r,ASSIGN)) ! 1085: error("no standard conversion of %t to %t",init->tp,p); ! 1086: p->base = b; ! 1087: r->base = bb; ! 1088: Pexpr cp = cast_cptr(Pclass(Pbase(pit)->b_name->tp),init,tbl,0); ! 1089: if (cp != init) { ! 1090: PERM(p); // or else it will be deleted twice! ! 1091: return new cast(p,cp); ! 1092: } ! 1093: } ! 1094: // no break ! 1095: } ! 1096: default: ! 1097: return init; ! 1098: } ! 1099: } ! 1100: ! 1101: static Pname Lcoerce, Rcoerce; ! 1102: extern int suppress_error; ! 1103: ! 1104: int try_to_demote(TOK oper, Ptype t1, Ptype t2) ! 1105: /* ! 1106: look at t1 and t2 and see if there are ``demotions'' of t1 and/or t2 ! 1107: so that ``t1 oper t2'' can be made legal ! 1108: ! 1109: return 0 is not ! 1110: 1 if there is exactly one way ! 1111: >1 if there is more than one way (if in doubt return 2) ! 1112: */ ! 1113: { ! 1114: //error('d',"try_to_demote(%k : %t : %t)",oper,t1,t2); ! 1115: ! 1116: Pname n1 = t1 ? t1->is_cl_obj() : 0; ! 1117: Pclass c1 = n1 ? Pclass(n1->tp) : 0; ! 1118: Pname n2 = t2 ? t2->is_cl_obj() : 0; ! 1119: Pclass c2 = n2 ? Pclass(n2->tp) : 0; ! 1120: ! 1121: Ptype lt = t1; ! 1122: Ptype rt = t2; ! 1123: ! 1124: Lcoerce = Rcoerce = 0; ! 1125: ! 1126: // if (oper == DOT) return 0; ! 1127: ! 1128: if (c1) ! 1129: switch (oper) { ! 1130: case ASSIGN: ! 1131: case ASPLUS: ! 1132: case ASMINUS: ! 1133: case ASMUL: ! 1134: case ASDIV: ! 1135: case ASMOD: ! 1136: case ASAND: ! 1137: case ASOR: ! 1138: case ASER: ! 1139: case ASLS: ! 1140: case ASRS: // don't coerce left hand side of assignment ! 1141: // c1 = 0; ! 1142: if (c1->memtbl->look("__as",0)) return 0; ! 1143: } ! 1144: else ! 1145: switch (oper) { ! 1146: case ADDROF: ! 1147: case INCR: ! 1148: case DECR: // don't coerce unary requiring an lval ! 1149: return 0; ! 1150: } ! 1151: ! 1152: if (c1) { ! 1153: //error('d',"c1 %t",c1); ! 1154: for (Pname on1 = c1->conv; on1; on1=on1->n_list) { ! 1155: Pfct f = Pfct(on1->tp); ! 1156: lt = f->returns; ! 1157: Pname cn = lt->is_cl_obj(); ! 1158: ! 1159: if (cn && (Lcoerce==0 || Lcoerce->tp->check(f,0))) { ! 1160: Pclass cl = Pclass(cn->tp); ! 1161: Pname n = cl->has_oper(oper); ! 1162: if (n == 0) continue; ! 1163: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem); ! 1164: Pfct nf = Pfct(n->tp); ! 1165: if (nf->base == FCT) { ! 1166: if (nf->nargs==1 ! 1167: && (nf->argtype->tp->check(t2,ARG)==0 ! 1168: || can_coerce(nf->argtype->tp,t2)==1) ! 1169: ) { ! 1170: if (Lcoerce) return 2; ! 1171: Lcoerce = on1; ! 1172: } ! 1173: } ! 1174: else { ! 1175: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) { ! 1176: Pfct nf = Pfct(gl->f->tp); ! 1177: if (nf->nargs==1 ! 1178: && (nf->argtype->tp->check(t2,ARG)==0 ! 1179: || can_coerce(nf->argtype->tp,t2)==1) ! 1180: ) { ! 1181: if (Lcoerce) return 2; ! 1182: Lcoerce = on1; ! 1183: } ! 1184: } ! 1185: } ! 1186: continue; ! 1187: } ! 1188: //if (lt->is_cl_obj()) continue; ! 1189: if (c2) { ! 1190: //error('d',"c2 %t",c2); ! 1191: for (Pname on2 = c2->conv; on2; on2=on2->n_list) { ! 1192: Pfct f = Pfct(on2->tp); ! 1193: rt = f->returns; ! 1194: if (rt->is_cl_obj()) continue; ! 1195: ! 1196: suppress_error = 1; ! 1197: int r1 = lt->kind(oper,0); ! 1198: int r2 = rt->kind(oper,0); ! 1199: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 1200: if (Lcoerce) { ! 1201: suppress_error = 0; ! 1202: return 2; ! 1203: } ! 1204: Lcoerce = on1; ! 1205: Rcoerce = on2; ! 1206: ! 1207: }; ! 1208: suppress_error = 0; ! 1209: } ! 1210: ! 1211: } ! 1212: else if (rt) { ! 1213: suppress_error = 1; ! 1214: int r1 = lt->kind(oper,0); ! 1215: int r2 = rt->kind(oper,0); ! 1216: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 1217: if (Lcoerce) { ! 1218: suppress_error = 0; ! 1219: return 2; ! 1220: } ! 1221: Lcoerce = on1; ! 1222: }; ! 1223: suppress_error = 0; ! 1224: } ! 1225: else { ! 1226: if (Lcoerce) return 2; ! 1227: Lcoerce = on1; ! 1228: } ! 1229: } ! 1230: } ! 1231: else if (c2) { ! 1232: //error('d',"c2 %n",c2); ! 1233: for (Pname on = c2->conv; on; on=on->n_list) { ! 1234: Pfct f = Pfct(on->tp); ! 1235: rt = f->returns; ! 1236: Pname cn = rt->is_cl_obj(); ! 1237: //error('d',"cn %n",cn); ! 1238: if (cn && (Rcoerce==0 || Rcoerce->tp->check(f,0))) { ! 1239: Pclass cl = Pclass(cn->tp); ! 1240: Pname n = cl->has_oper(oper); ! 1241: if (n == 0) continue; ! 1242: ! 1243: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem); ! 1244: Pfct nf = Pfct(n->tp); ! 1245: if (nf->base == FCT) { ! 1246: if (nf->nargs == 0) { ! 1247: if (Lcoerce || Rcoerce) return 2; ! 1248: Rcoerce = on; ! 1249: } ! 1250: } ! 1251: else { ! 1252: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) ! 1253: if (Pfct(gl->f->tp)->nargs == 0) { ! 1254: if (Lcoerce || Rcoerce) return 2; ! 1255: Rcoerce = on; ! 1256: } ! 1257: } ! 1258: continue; ! 1259: } ! 1260: //if (rt->is_cl_obj()) continue; ! 1261: suppress_error = 1; ! 1262: int r1 = lt->kind(oper,0); ! 1263: int r2 = rt->kind(oper,0); ! 1264: ! 1265: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 1266: if (Lcoerce || Rcoerce) { ! 1267: suppress_error = 0; ! 1268: return 2; ! 1269: } ! 1270: Rcoerce = on; ! 1271: } ! 1272: suppress_error = 0; ! 1273: } ! 1274: } ! 1275: ! 1276: //error('d',"->%d || %d",Lcoerce,Rcoerce); ! 1277: return (Lcoerce || Rcoerce); ! 1278: } ! 1279: ! 1280: Pexpr expr::try_to_overload(Ptable tbl) ! 1281: { ! 1282: // TOK bb = (base==DEREF && e2==0) ? MUL : base; ! 1283: //error('d',"try_to_overload %k %k",base,base); ! 1284: ! 1285: Pname n1 = 0; ! 1286: Ptype t1 = 0; ! 1287: ! 1288: if (e1) { ! 1289: t1 = e1->tp; ! 1290: Ptype tpx = t1; ! 1291: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 1292: n1 = tpx->is_cl_obj(); ! 1293: } ! 1294: ! 1295: ! 1296: TOK bb = base; ! 1297: switch (bb) { ! 1298: case DEREF: ! 1299: if (e2 == 0) bb = MUL; ! 1300: // no break; ! 1301: case CALL: ! 1302: case G_CALL: ! 1303: if (n1 == 0) return 0; // ignore type of argument list ! 1304: } ! 1305: ! 1306: Pname n2 = 0; ! 1307: Ptype t2 = 0; ! 1308: ! 1309: if (e2 && e2->base!=ELIST) { ! 1310: t2 = e2->tp; ! 1311: Ptype tpx = t2; ! 1312: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 1313: n2 = tpx->is_cl_obj(); ! 1314: } ! 1315: ! 1316: if (n1==0 && n2==0) return 0; ! 1317: if (n1 && n1->tp == 0) return 0; // make_assign() fudge ! 1318: //error('d',"t1 %t t2 %t",t1,t2); ! 1319: //error('d',"n1 %n n2 %n",n1,n2); ! 1320: /* first try for non-member function: op(e1,e2) or op(e2) or op(e1) */ ! 1321: Pexpr oe2 = e2; ! 1322: Pexpr ee2 = (e2 && e2->base!=ELIST) ? e2 = new expr(ELIST,e2,0) : 0; ! 1323: Pexpr ee1 = e1 ? new expr(ELIST,e1,e2) : ee2; ! 1324: char* obb = oper_name(bb); ! 1325: Pname gname = gtbl->look(obb,0);// first look at member functions ! 1326: // then if necessary check for ambiguities ! 1327: int go = gname ? over_call(gname,ee1) : 0; ! 1328: //error('d',"go %d",go); ! 1329: if (go) gname = Nover; ! 1330: ! 1331: if (n1) { ! 1332: if (bb == ASSIGN) { ! 1333: Pclass c1 = Pclass(n1->tp); ! 1334: //error('d',"look %k %d",bb,c1->memtbl->look(obb,0)); ! 1335: if (c1->memtbl->look(obb,0)==0) { ! 1336: Pclass bcl = c1->baselist?c1->baselist->bclass:0; ! 1337: if (n2==0 ! 1338: || (Pclass(n2->tp)!=c1 ! 1339: && Pclass(n2->tp)->has_base(c1)==0)) { ! 1340: // if legal, a=1 can be optimized to a.ctor(1) ! 1341: if (2 < go) goto glob; ! 1342: return 0; ! 1343: } ! 1344: ! 1345: if (bcl ! 1346: && c1->obj_size!=bcl->obj_size ! 1347: && bcl->memtbl->look(obb,0)) { ! 1348: // cannot inherit from smaller base class ! 1349: // make_assignment(n1); ! 1350: // return try_to_overload(tbl); ! 1351: goto mkas; ! 1352: } ! 1353: ! 1354: if (c1->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 1355: // make operator=() if ! 1356: // no base (shouldn't happen ! 1357: // different (smaller) sized base ! 1358: // two bases ! 1359: mkas: ! 1360: if (2 < go) goto glob; ! 1361: // make_assignment(n1); ! 1362: // return try_to_overload(tbl); ! 1363: return make_assignment(n1) ? try_to_overload(tbl) : 0; ! 1364: } ! 1365: //error('d',"n2 %n",n2); ! 1366: // if (n2 && Pclass(n2->tp)==c1) ! 1367: return 0; ! 1368: } ! 1369: // now take care of other assignments, ! 1370: } ! 1371: ! 1372: Pexpr mn = Pclass(n1->tp)->find_name(obb,0); ! 1373: Pname mname = Pname(mn); ! 1374: //error('d',"mn %n %d %k %s",mname,mn,mn?mn->base:0,obb); ! 1375: if (mname == 0) goto glob; ! 1376: ! 1377: zaq: ! 1378: switch (mname->base) { ! 1379: case REF: ! 1380: case MDOT: ! 1381: mname = Pname(Pexpr(mname)->mem); ! 1382: goto zaq; ! 1383: } ! 1384: ! 1385: int mo = over_call(mname,e2); ! 1386: //error('d',"mo %d (go %d)",mo,go); ! 1387: if (mo==0 || mo<go) ! 1388: goto glob; ! 1389: else if (mo && mo==go) { ! 1390: //error('d',"t1 %t t2 %t",t1,t2); ! 1391: if (gname->tp->base == OVERLOAD) { // find right version ! 1392: for (Plist l = Pgen(gname->tp)->fct_list; l; l=l->l) { ! 1393: Pname n = l->f; ! 1394: int x = over_call(n,ee1); ! 1395: if (x == go) { ! 1396: gname = n; ! 1397: break; ! 1398: } ! 1399: } ! 1400: } ! 1401: //error('d',"gname %n: %t",gname,gname->tp); ! 1402: Pname aa = Pfct(gname->tp)->argtype; ! 1403: Pptr p; ! 1404: Ptype gt1 = aa->tp; ! 1405: if (p = gt1->is_ref()) gt1 = p->typ; ! 1406: Ptype gt2 = aa->n_list->tp; ! 1407: //error('d',"gt1 %t gt2 %t",gt1,gt2); ! 1408: if (mname->tp->base == OVERLOAD) { // find right version ! 1409: for (Plist l = Pgen(mname->tp)->fct_list; l; l=l->l) { ! 1410: Pname n = l->f; ! 1411: int x = over_call(n,e2); ! 1412: if (x == mo) { ! 1413: mname = n; ! 1414: break; ! 1415: } ! 1416: } ! 1417: } ! 1418: //error('d',"mname %n: %t",mname,mname->tp); ! 1419: Ptype mt1 = Pfct(mname->tp)->f_this->tp; ! 1420: mt1 = Pptr(mt1)->typ; ! 1421: Ptype mt2 = Pfct(mname->tp)->argtype->tp; ! 1422: //error('d',"mt1 %t mt2 %t",mt1,mt2); ! 1423: Pname mm = new name; ! 1424: Pname a1 = new name; ! 1425: a1->tp = mt1; ! 1426: Pname a2 = new name; ! 1427: a2->tp = mt2; ! 1428: a1->n_list = a2; ! 1429: mm->tp = new fct(void_type,a1,2); ! 1430: Pname gg = new name; ! 1431: Pname a3 = new name; ! 1432: a3->tp = gt1; ! 1433: Pname a4 = new name; ! 1434: a4->tp = gt2; ! 1435: a3->n_list = a4; ! 1436: gg->tp = new fct(void_type,a3,1); ! 1437: extern Pname dominate(Pname,Pname,Pexpr,int,int); ! 1438: aa = dominate(gg,mm,ee1,0,1); ! 1439: delete a1; ! 1440: delete a2; ! 1441: delete a3; ! 1442: delete a4; ! 1443: delete gg->tp; ! 1444: delete mm->tp; ! 1445: if (aa == 0) { ! 1446: delete gg; ! 1447: delete mm; ! 1448: error("ambiguous operandTs%n and%t for%k",n1,t2,bb); ! 1449: tp = any_type; ! 1450: return this; ! 1451: } ! 1452: else if (aa == gg) { ! 1453: delete gg; ! 1454: delete mm; ! 1455: goto glob; ! 1456: } ! 1457: delete gg; ! 1458: delete mm; ! 1459: } ! 1460: else if (mo < 2) { // user-defined conversion user ! 1461: if (try_to_demote(bb,t1,t2)) ! 1462: error("ambiguous use of overloaded%k",bb); ! 1463: } ! 1464: ! 1465: base = G_CALL; // e1.op(e2) or e1.op() ! 1466: Pname xx = new name(mname->string); // do another lookup ! 1467: // . suppresses virtual ! 1468: e1 = new ref(DOT,e1,xx); ! 1469: if (ee1) delete ee1; ! 1470: return typ(tbl); ! 1471: } ! 1472: ! 1473: if (n2 && e1==0) { /* look for unary operator */ ! 1474: Pexpr mn = Pclass(n2->tp)->find_name(obb,0); ! 1475: Pname mname = Pname(mn); ! 1476: if (mname == 0) goto glob; ! 1477: zaqq: ! 1478: switch (mname->base) { ! 1479: case REF: ! 1480: case MDOT: ! 1481: mname = Pname(Pexpr(mname)->mem); ! 1482: goto zaqq; ! 1483: } ! 1484: ! 1485: switch (mname->n_scope) { ! 1486: default: goto glob; ! 1487: case 0: ! 1488: case PUBLIC: break; // try e2.op() ! 1489: } ! 1490: ! 1491: int mo = over_call(mname,0); ! 1492: //error('d',"e2 mo %d (go %d)",mo,go); ! 1493: if (mo==0 || mo<go) ! 1494: goto glob; ! 1495: else if (mo==go) { ! 1496: error("ambiguous operandT%n for%k",n2,bb); ! 1497: tp = any_type; ! 1498: return this; ! 1499: } ! 1500: else if (mo < 2) { // user-defined conversion user ! 1501: if (try_to_demote(bb,t1,t2)) ! 1502: error("ambiguous use of overloaded%k",bb); ! 1503: } ! 1504: base = G_CALL; // e2.op() ! 1505: Pname xx = new name(Nover->string); // do another lookup ! 1506: // . suppresses virtual ! 1507: e1 = new ref(DOT,oe2,xx); ! 1508: e2 = 0; ! 1509: if (ee2) delete ee2; ! 1510: if (ee1 && ee1!=ee2) delete ee1; ! 1511: return typ(tbl); ! 1512: } ! 1513: ! 1514: glob: ! 1515: //error('d',"glob %d",go); ! 1516: ! 1517: if (go) { ! 1518: if (go < 2) { // user-defined conversion necessary => binary ! 1519: if (try_to_demote(bb,t1,t2)) ! 1520: error("ambiguous use of overloaded%k: %t and %t",bb,t1,t2); ! 1521: } ! 1522: ! 1523: base = G_CALL; // ::op(e1,e2) or ::op(e1) or ::op(e2) ! 1524: //error('d',"gname %n %t",gname,gname->tp); ! 1525: e1 = new name(gname->string); ! 1526: Pname(e1)->n_qualifier = sta_name; // look only for globals ! 1527: e2 = ee1; ! 1528: return typ(tbl); ! 1529: } ! 1530: ! 1531: if (ee2) delete ee2; ! 1532: if (ee1 && ee1!=ee2) delete ee1; ! 1533: e2 = oe2; ! 1534: ! 1535: //error('d',"bb %d %k",bb,bb); ! 1536: switch (bb) { ! 1537: case CM: ! 1538: case G_CM: ! 1539: case G_ADDROF: ! 1540: return 0; ! 1541: case ASSIGN: ! 1542: if (n1 ! 1543: && n2 ! 1544: && (n1->tp==n2->tp || Pclass(n2->tp)->has_base(Pclass(n1->tp)))) { ! 1545: if (make_assignment(n1)) ! 1546: return try_to_overload(tbl); ! 1547: else ! 1548: return 0; ! 1549: } ! 1550: case DEREF: ! 1551: case CALL: ! 1552: if (n1 == 0) break; ! 1553: ! 1554: default: /* look for conversions to basic types */ ! 1555: if (n1 ! 1556: && Pclass(n1->tp)->conv ! 1557: && (bb==ANDAND || bb==OROR)) { ! 1558: e1 = check_cond(e1,bb,tbl); ! 1559: return 0; ! 1560: } ! 1561: ! 1562: if (n2 ! 1563: && Pclass(n2->tp)->conv ! 1564: && (bb==ANDAND || bb==OROR || bb==NOT)) { ! 1565: e2 = check_cond(e2,bb,tbl); ! 1566: return 0; ! 1567: } ! 1568: ! 1569: switch (try_to_demote(bb,t1,t2)) { ! 1570: default: ! 1571: if (Lcoerce) error("ambiguous conversion of%n",n1); ! 1572: if (Rcoerce) error("ambiguous conversion of%n",n2); ! 1573: case 0: ! 1574: break; ! 1575: case 1: ! 1576: if (Lcoerce) { ! 1577: ! 1578: Pname xx = new name(Lcoerce->string); ! 1579: Pref r = new ref(DOT,e1,xx); ! 1580: e1 = new expr(G_CALL,r,0); ! 1581: } ! 1582: ! 1583: if (Rcoerce) { ! 1584: ! 1585: Pname xx = new name(Rcoerce->string); ! 1586: Pref r = new ref(DOT,e2,xx); ! 1587: e2 = new expr(G_CALL,r,0); ! 1588: } ! 1589: return typ(tbl); ! 1590: } ! 1591: ! 1592: switch (bb) { ! 1593: case CM: ! 1594: case ADDROF: // has legal built-in meaning ! 1595: return 0; ! 1596: } ! 1597: ! 1598: if (t1 && t2) ! 1599: error("bad operandTs%t%t for%k",t1,t2,bb); ! 1600: else ! 1601: error("bad operandT%t for%k",t1?t1:t2,bb); ! 1602: ! 1603: tp = any_type; ! 1604: return this; ! 1605: } ! 1606: ! 1607: return 0; ! 1608: } ! 1609: ! 1610: Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast) ! 1611: /* ! 1612: "ee" is being cast to pointer object of class "ccl" ! 1613: if necessary modify "ee" ! 1614: */ ! 1615: { ! 1616: ! 1617: // Ptype etp = ee->tp; ! 1618: //error('d',"cast_cptr %k ccl %t ee->tp %t",ee->tp->base,ccl,ee->tp); ! 1619: ! 1620: // if (etp->base!=PTR && etp->base!=RPTR) return ee; ! 1621: Ptype etp = ee->tp->is_ptr_or_ref(); ! 1622: if (etp == 0) return ee; ! 1623: ! 1624: Pname on = Pptr(etp)->typ->is_cl_obj(); ! 1625: if (on == 0) return ee; ! 1626: ! 1627: Pclass ocl = Pclass(on->tp); ! 1628: if (ocl==ccl || ccl==0 || ocl==0) return ee; ! 1629: ! 1630: //error('d',"cast_cptr %t(%t) real %d",ccl,ocl,real_cast); ! 1631: int oo = 0; ! 1632: Pexpr r = 0; ! 1633: ! 1634: if (ocl->baselist ! 1635: && (ocl->baselist->bclass!=ccl || ocl->baselist->base!=NAME)) { ! 1636: // casting derived to second or virtual base? ! 1637: Nptr = 0; ! 1638: vcllist->clear(); ! 1639: vcllist=0; ! 1640: int x = is_unique_base(ocl,ccl->string,0); ! 1641: //error('d',"x1 %d",x); ! 1642: if (Nvis) { ! 1643: if (real_cast==0) ! 1644: error("cast:%n* ->B%t*; privateBC",on,ccl); ! 1645: else if (warning_opt) ! 1646: error('w',"cast:%n* ->B%t*; privateBC",on,ccl); ! 1647: real_cast = 1; // suppress further error mesages ! 1648: Nvis = 0; ! 1649: } ! 1650: ! 1651: switch (x) { ! 1652: default: ! 1653: error("cast:%n* ->B%t*;%t isB more than once",on,ccl,ccl); ! 1654: case 0: // unrelated; ! 1655: break; ! 1656: case 1: ! 1657: oo = Noffset; ! 1658: break; ! 1659: } ! 1660: ! 1661: if (Nptr) { // => ee?Nptr:0 ! 1662: //error('d',"nptr"); ! 1663: if (ocl->c_body==1) ocl->dcl_print(0); ! 1664: Nptr->mem = ee; // ee->Pbase_class ! 1665: Nptr->i1 = 3; ! 1666: if (ee->base==ADDROF || ee->base==G_ADDROF) ! 1667: ee = Nptr; ! 1668: else { ! 1669: Pexpr p = new expr(QUEST,Nptr,zero); ! 1670: extern nin; ! 1671: nin = 1; ! 1672: if (ee->not_simple()) { // need temp ! 1673: Ptype t = ee->tp; ! 1674: Pname pp = make_tmp('N',t,tbl); ! 1675: Pname(pp)->n_assigned_to = 1; ! 1676: ee = new expr(ASSIGN,pp,ee); ! 1677: ee->tp = t; ! 1678: Nptr->mem = pp; ! 1679: } ! 1680: nin = 0; ! 1681: p->cond = ee; ! 1682: //error('d',"p->tp %t",ee->tp); ! 1683: p->tp = ee->tp; ! 1684: ee = p; ! 1685: } ! 1686: } ! 1687: } ! 1688: ! 1689: if (ccl->baselist ! 1690: && (ccl->baselist->bclass!=ocl || ccl->baselist->base!=NAME)) { ! 1691: // casting second or virtual base to derived? ! 1692: Nptr = 0; ! 1693: vcllist->clear(); ! 1694: vcllist=0; ! 1695: int x = is_unique_base(ccl,ocl->string,0); ! 1696: //error('d',"x2 %d",x); ! 1697: switch (x) { ! 1698: default: ! 1699: error("cast:%n* ->derived%t*;%n isB more than once",on,ccl,on); ! 1700: case 0: // unrelated; ! 1701: break; ! 1702: case 1: ! 1703: oo = -Noffset; ! 1704: if (Nptr) ! 1705: error("cast:%n* ->derived%t*;%n is virtualB",on,ccl,on); ! 1706: break; ! 1707: } ! 1708: Nvis = 0; // visibility no concern when converting ! 1709: // from base to derived ! 1710: ! 1711: ! 1712: } ! 1713: //error('d',"oo %d ee %k",oo,ee->base); ! 1714: if (oo) { // => ee?ee+offset:0 ! 1715: if (ee->base==ADDROF || ee->base==G_ADDROF) ! 1716: ee = rptr(ee->tp,ee,oo); ! 1717: else { ! 1718: Pexpr p; ! 1719: extern nin; ! 1720: nin = 1; ! 1721: if (ee->not_simple()) { // need temp ! 1722: Ptype t = ee->tp; ! 1723: Pname pp = make_tmp('M',t,tbl); ! 1724: Pname(pp)->n_assigned_to = 1; ! 1725: ee = new expr(ASSIGN,pp,ee); ! 1726: ee->tp = t; ! 1727: p = rptr(t,pp,oo); ! 1728: } ! 1729: else ! 1730: p = rptr(ee->tp,ee,oo); ! 1731: nin = 0; ! 1732: Pexpr pp = new expr(QUEST,p,zero); ! 1733: pp->tp = ee->tp; ! 1734: pp->cond = ee; ! 1735: ee = pp; ! 1736: } ! 1737: } ! 1738: ! 1739: if (ocl->has_base(ccl) && Nvis) { ! 1740: if (real_cast==0) ! 1741: error("cast:%n* ->B%t*; privateBC",on,ccl); ! 1742: else if (warning_opt) ! 1743: error('w',"cast:%n* ->B%t*; privateBC",on,ccl); ! 1744: Nvis = 0; ! 1745: } ! 1746: ! 1747: //error('d',"return %d %k %t",ee,ee->base,ee->tp); ! 1748: return ee; ! 1749: } ! 1750: ! 1751: Pexpr expr::donew(Ptable tbl) ! 1752: { ! 1753: Ptype tt = tp2; ! 1754: Ptype tpx = tt; ! 1755: bit v = 0; ! 1756: bit old = new_type; ! 1757: int init = 0; // non-constructor initialization ! 1758: new_type = 1; ! 1759: ! 1760: tt->dcl(tbl); ! 1761: new_type = old; ! 1762: //error('d',"donew %d %d (%k) tt %t",e1,e2,e2?e2->base:0,tt); ! 1763: if (e1) e1 = e1->typ(tbl); ! 1764: if (e2) e2 = e2->typ(tbl); ! 1765: ll: ! 1766: //error('d',"ll %d",tt->base); ! 1767: switch (tt->base) { ! 1768: default: ! 1769: if ( e1) { ! 1770: if (v) { ! 1771: error("Ir for array created using \"new\""); ! 1772: break; ! 1773: } ! 1774: init = 1; ! 1775: } ! 1776: // if (e1) { ! 1777: // error("Ir for nonCO created using \"new\""); ! 1778: // e1 = 0; ! 1779: // } ! 1780: break; ! 1781: case VEC: ! 1782: if (v && Pvec(tt)->dim) error("only 1st array dimension can be non-constant"); ! 1783: if (Pvec(tt)->size==0 && Pvec(tt)->dim==0) error("array dimension missingin `new'"); ! 1784: // if (Pvec(tt)->dim==zero) { ! 1785: // Pvec(tt)->size = 0; ! 1786: // Pvec(tt)->dim = 0; ! 1787: // } ! 1788: v++; ! 1789: tt = Pvec(tt)->typ; ! 1790: goto ll; ! 1791: case TYPE: ! 1792: tt = Pbase(tt)->b_name->tp; ! 1793: goto ll; ! 1794: case VOID: ! 1795: error("badT for `new': void"); ! 1796: break; ! 1797: case COBJ: ! 1798: { Pname cn = Pbase(tt)->b_name; ! 1799: Pclass cl = Pclass(cn->tp); ! 1800: Pname icn = (e1 && e1->base!=ELIST) ? e1->tp->is_cl_obj() : 0; ! 1801: Pclass icl = icn ? Pclass(icn->tp) : 0; ! 1802: ! 1803: if (cl->c_abstract) { ! 1804: error("`new' of abstractC%t",cl); ! 1805: break; ! 1806: } ! 1807: ! 1808: if (v && e1) { ! 1809: error("Ir for array ofCO created using \"new\""); ! 1810: break; ! 1811: } ! 1812: ! 1813: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1814: error("new%n;%n isU",cn,cn); ! 1815: break; ! 1816: } ! 1817: ! 1818: Pname ctor = cl->has_ctor(); ! 1819: ! 1820: if (ctor) { ! 1821: if (v) { ! 1822: Pname ic; ! 1823: if ((ic = cl->has_ictor())==0) { ! 1824: error("array ofC%n that does not have aK taking noAs",cn); ! 1825: break; ! 1826: } ! 1827: ! 1828: if (Pfct(ic->tp)->nargs) { ! 1829: error("defaultAs forK for array ofC%n",cn); ! 1830: break; ! 1831: } ! 1832: } ! 1833: ! 1834: if (icl ! 1835: && cl->has_itor()==0 // incomplete: ! 1836: // what if X(Y&) exists ! 1837: // for class Y : X ? ! 1838: && (icl==cl || icl->has_base(cl))) { ! 1839: init = 1; ! 1840: break; ! 1841: } ! 1842: e1 = call_ctor(tbl,0,ctor,e1); ! 1843: } ! 1844: else if (e1) { ! 1845: if (icl==cl || icl->has_base(cl)) ! 1846: init = 1; ! 1847: else ! 1848: error("new%n(As ); %n does not have aK",cn,cn); ! 1849: } ! 1850: } ! 1851: } ! 1852: ! 1853: if (init) { ! 1854: Pname tmp = make_tmp('N',tt->addrof(),tbl); ! 1855: e1 = e1->typ(tbl); ! 1856: if (tt->check(e1->tp,ASSIGN)) ! 1857: error("badIrT %t for new operator (%t X)",e1->tp,tt); ! 1858: e1 = new expr(0,tmp,e1); ! 1859: tmp->assign(); ! 1860: } ! 1861: ! 1862: // tp = (v) ? tpx : tpx->addrof(); ! 1863: switch (v) { ! 1864: case 0: ! 1865: tp = tpx->addrof(); ! 1866: break; ! 1867: case 1: ! 1868: tp = tpx; ! 1869: break; ! 1870: default: ! 1871: tp = tpx; ! 1872: } ! 1873: //error('d',"donew(%d) -> %t",v,tp); ! 1874: return this; ! 1875: } ! 1876: ! 1877: static is_dataMemPtr( Pexpr ee ) ! 1878: /* this is utterly implementation dependent ! 1879: * called by expr::lval to determine ! 1880: * const objects bounds to pointers to data members ! 1881: */ ! 1882: { ! 1883: Pexpr te = ee->e1; ! 1884: if ( te == 0 ) return 0; ! 1885: if ( te->base != PLUS ) return 0; ! 1886: if ( (te = te->e2) == 0 ) return 0; ! 1887: if ( te->base != MINUS ) return 0; ! 1888: if ( (te = te->e1) == 0 ) return 0; ! 1889: if ( te->base != CAST ) return 0; ! 1890: if ( (te = te->e1) == 0 ) return 0; ! 1891: if ( te->tp->base != PTR ) return 0; ! 1892: if ( Pptr(te)->memof == 0 ) return 0; ! 1893: return 1; ! 1894: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.