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