|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/expr3.c 1.14" */ ! 2: /*************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: expr3.c: ! 11: ! 12: type check function calls, casts, and explicit coercions ! 13: ! 14: ************************************************************************/ ! 15: ! 16: #include "cfront.h" ! 17: #include "size.h" ! 18: #include "Block.h" ! 19: #include "Bits.h" ! 20: ! 21: Blockdeclare(Pname) ! 22: Blockdeclare(int) ! 23: typedef Block(Pname) Block_Pname; ! 24: Blockdeclare(Block_Pname) ! 25: ! 26: extern Pname conv_dominates(Pname,Pname); ! 27: static Pname bestOfPair(Pname, Pname, Ptype); ! 28: static Bits intersectRule(const Block(Block_Pname)&, int, Pexpr); ! 29: static Bits bestMatch(const Block(Pname)&, int, Ptype); ! 30: static Pname breakTie(const Block(Pname)&, Bits&, Pexpr, int); ! 31: static void fmError(int, const Block(Pname)&, Pexpr); ! 32: ! 33: static refd; // initialization routine called by ref_init, do not apply itor ! 34: static no_sti; ! 35: static int miFlag; ! 36: extern int stat_init; ! 37: ! 38: int pr_dominate(Ptype t1, Ptype t2) ! 39: /* ! 40: */ ! 41: { ! 42: Pname cn1 = t1->is_cl_obj(); ! 43: Pname cn2 = t2->is_cl_obj(); ! 44: ! 45: if (cn1==0 || cn2==0) { ! 46: Ptype p1 = t1->is_ptr(); ! 47: Ptype p2 = t2->is_ptr(); ! 48: if (p1 && p2) { // pointers ! 49: cn1 = Pptr(p1)->typ->is_cl_obj(); ! 50: cn2 = Pptr(p2)->typ->is_cl_obj(); ! 51: if (cn1==0 || cn2==0) return 0; ! 52: } ! 53: else { ! 54: p1 = t1->is_ref(); ! 55: p2 = t2->is_ref(); ! 56: if (p1 && p2) { // references ! 57: cn1 = Pptr(p1)->typ->is_cl_obj(); ! 58: cn2 = Pptr(p2)->typ->is_cl_obj(); ! 59: if (cn1==0 || cn2==0) return 0; ! 60: } ! 61: else ! 62: return 0; // not the same and not classes ! 63: } ! 64: } ! 65: Pclass c1 = Pclass(cn1->tp); ! 66: Pclass c2 = Pclass(cn2->tp); ! 67: ! 68: if (c1->has_base(c2)) return 1; ! 69: if (c2->has_base(c1)) return 2; ! 70: return 0; ! 71: } ! 72: ! 73: Pname Ntmp; ! 74: ! 75: Pname make_tmp(char c, Ptype t, Ptable tbl) ! 76: { ! 77: int dt = 0; ! 78: Pname tn = tbl->t_name; ! 79: Pname cn = t->is_cl_obj(); ! 80: ! 81: if (tn && tn->tp) error('s',"defaultA too complicated"); ! 82: if (cn && Pclass(cn->tp)->has_dtor()) dt = 1; ! 83: if (Ntmp == 0 && dt ) Ntmp = cn; ! 84: ! 85: //error('d',"tbl %d cstmt %d %d sti %d",tbl,Cstmt,Cstmt?Cstmt->memtbl:0,sti_tbl); ! 86: if (Cstmt) { // make Cstmt into a block ! 87: if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0); ! 88: tbl = Cstmt->memtbl; ! 89: } ! 90: else if (tbl == gtbl && no_sti == 0) { ! 91: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0); ! 92: tbl = sti_tbl; ! 93: } ! 94: ! 95: Pname tmpx = new name(make_name(c)); ! 96: tmpx->where = no_where; ! 97: tmpx->tp = t; ! 98: (void) t->tsizeof(); ! 99: if ( t->base == COBJ ) { ! 100: Pclass cl = Pclass(Pbase(t)->b_name->tp); ! 101: if ( cl->lex_level ) tmpx->lex_level = cl->lex_level; ! 102: } ! 103: ! 104: TOK scop = ARG; ! 105: if (stat_init && dt) { ! 106: tmpx->n_sto = STATIC; scop = ARGS; ! 107: } ! 108: ! 109: // ARG[S]: no init; ARGS: static dtor ! 110: Pname tmp = tmpx->dcl(tbl,scop); ! 111: delete tmpx; ! 112: ! 113: // n_scope == ARGS sets static dtor in simpl2.c ! 114: tmp->n_scope = (scop==ARG) ? FCT : ARGS; ! 115: return tmp; ! 116: } ! 117: ! 118: Pexpr init_tmp(Pname tmp, Pexpr init, Ptable tbl) ! 119: { ! 120: Pname cn = tmp->tp->is_cl_obj(); ! 121: Pname ct = cn ? Pclass(cn->tp)->has_itor() : 0; ! 122: ! 123: tmp->n_assigned_to = 1; ! 124: //error('d',"init_tmp %n ct %n refd %d",tmp,ct,refd); ! 125: if (ct) { // must initialize ! 126: if (refd) { ! 127: //error('d',"'orrible %k",init->e1->base); ! 128: switch (init->e1->base) { // 'orrible 'ack ! 129: case NAME: ! 130: case REF: ! 131: case DEREF: ! 132: if (init->e1->tp->is_ptr()) ! 133: init = init->e1; ! 134: else ! 135: init = new expr(G_CM,init,init->e1->address()); ! 136: ! 137: } ! 138: if (ct->tp->base == OVERLOAD) ct = Pgen(ct->tp)->fct_list->f; // first fct ! 139: tbl = 0; ! 140: } ! 141: return call_ctor(tbl,tmp,ct,init,DOT); ! 142: } ! 143: Pexpr ass = new expr(ASSIGN,tmp,init); // no ctor: can assign ! 144: ass->tp = tmp->tp; ! 145: return ass; ! 146: } ! 147: ! 148: int exact3(Pname nn, Ptype at) ! 149: /* ! 150: return 1 if ! 151: match with standard conversions ! 152: */ ! 153: { ! 154: if (nn == 0) return 0; ! 155: Ptype nt = nn->tp->skiptypedefs(); ! 156: ! 157: if (at == nt) return 1; ! 158: ! 159: switch (nt->base) { ! 160: case RPTR: ! 161: if (nt->base==RPTR && Pptr(nt)->typ->check(at,COERCE)==0) ! 162: return 1; ! 163: if (at==zero_type && Pptr(nt)->typ->is_ptr()==0) return 0; ! 164: if (nt->check(at,COERCE)) { ! 165: Pptr pt = at->addrof(); ! 166: nt->base = PTR; // handle derived classes ! 167: if (nt->check(pt,COERCE)) { ! 168: nt->base = RPTR; ! 169: delete pt; ! 170: return 0; ! 171: } ! 172: nt->base = RPTR; ! 173: delete pt; ! 174: } ! 175: break; ! 176: default: ! 177: switch (at->base) { ! 178: default: ! 179: if (nt->check(at,COERCE)) return 0; ! 180: break; ! 181: case OVERLOAD: ! 182: // the actual argument is an overloaded function ! 183: // we'll try each instance until one matches ! 184: register Plist gl; ! 185: int no_match = 1; ! 186: ! 187: for (gl = Pgen(at)->fct_list; gl; gl=gl->l) { ! 188: if (nt->check(gl->f->tp,COERCE)==0) { ! 189: no_match = 0; ! 190: break; ! 191: } ! 192: } ! 193: ! 194: if ( no_match ) return 0; ! 195: } ! 196: } ! 197: return 1; ! 198: } ! 199: ! 200: int exact1(Pname nn, Ptype at) ! 201: /* ! 202: return 1 if ! 203: exact match with ! 204: T <-> const T ! 205: X -> X& ! 206: T* -> const T* ! 207: T* -> T*const ! 208: taken into account ! 209: */ ! 210: { ! 211: if (nn == 0) return 0; ! 212: Ptype nt = nn->tp; ! 213: if (at == nt) return 1; ! 214: ! 215: if (nt->check(at,0)) { ! 216: // handle T <-> const T ! 217: if (const_problem && nt->base != PTR) return 1; ! 218: ! 219: Pptr rt = nt->is_ref(); //handle X -> X& ! 220: if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) ! 221: return 1; ! 222: ! 223: Pptr art = at->is_ptr(); ! 224: if (rt && art) return 0; // ptrs do not match refs ! 225: ! 226: // handle T* -> const T* and ! 227: // T* -> T*const ! 228: if (rt || (rt = nt->is_ptr())) { ! 229: if (art == 0) art = at->is_ref(); ! 230: if (art) { ! 231: if (art->typ->check(rt->typ,0)) { ! 232: if (const_problem && ! 233: Pbase(art->typ)->b_const != 1) ! 234: return 1; ! 235: } ! 236: else // T* -> T*const ! 237: return 1; ! 238: } ! 239: } ! 240: return 0; ! 241: } ! 242: return 1; ! 243: } ! 244: ! 245: static Pexpr Ninit; // default argument used; ! 246: int Nstd; // standard coercion used (derived* =>base* or int=>long or ...) ! 247: ! 248: int exact2(Pname nn, Ptype at) ! 249: /* ! 250: return 1 if ! 251: do integral promotion and float->double on at, then match ! 252: */ ! 253: { ! 254: //error('d',"exact2 nt %t at %t",nn?nn->tp:0,at); ! 255: at = at->skiptypedefs(); ! 256: switch (at->base) { ! 257: case EOBJ: ! 258: at = Penum(Pbase(at)->b_name->tp)->e_type; ! 259: break; ! 260: case ZTYPE: ! 261: at = int_type; ! 262: break; ! 263: case CHAR: ! 264: case SHORT: ! 265: at = (Pbase(at)->b_unsigned && at->tsizeof()==SZ_INT) ? uint_type : int_type; ! 266: break; ! 267: case FLOAT: ! 268: at = double_type; ! 269: } ! 270: ! 271: if (nn == 0) return 0; ! 272: Ptype nt = nn->tp; ! 273: return exact1(nn,at); ! 274: } ! 275: ! 276: Pname Ncoerce; ! 277: int ref_cast; ! 278: ! 279: bit can_coerce(Ptype t1, Ptype t2) ! 280: /* ! 281: return number of possible coercions of t2 into t1, ! 282: Ncoerce holds a coercion function (not constructor), if found ! 283: */ ! 284: { ! 285: int zz = 0; ! 286: Ncoerce = 0; ! 287: if (t2->base == ANY) return 0; ! 288: //error('d',"can_coerce t1 %t t2 %t",t1, t2); ! 289: ! 290: t1 = t1->skiptypedefs(); ! 291: ! 292: switch (t1->base) { ! 293: case RPTR: ! 294: if (t1->check(t2->skiptypedefs()->addrof(),COERCE) == 0) return 1; ! 295: if (ref_cast) break;//return 0; // (T&): no coercions ! 296: // except operator T&() ! 297: Ptype tt1 = Pptr(t1)->typ->skiptypedefs(); ! 298: int bc; ! 299: if ( tt1->base != PTR && tt1->base != RPTR ) { ! 300: bc = Pbase(tt1)->b_const; ! 301: Pbase(tt1)->b_const = 0; ! 302: } ! 303: int i = can_coerce(tt1,t2); ! 304: if ( tt1->base != PTR && tt1->base != RPTR ) ! 305: Pbase(tt1)->b_const = bc; ! 306: if (i) return i; ! 307: zz = 1; ! 308: } ! 309: ! 310: Pname c1 = t1->is_cl_obj(); ! 311: Pname c2 = t2->is_cl_obj(); ! 312: int val = 0; ! 313: if (ref_cast || zz) goto oper_coerce; ! 314: if (c1) { ! 315: Pclass cl = Pclass(c1->tp); ! 316: if (c2 && c2->tp==cl) return 1; ! 317: ! 318: // A more comprehensive test for template classes ! 319: if (c2 && (Pclass(c1->tp)->same_class(Pclass(c2->tp)))) ! 320: return 1 ; ! 321: ! 322: /* look for constructor ! 323: with one argument ! 324: or with default for second argument ! 325: of acceptable type ! 326: */ ! 327: Pname ctor = cl->has_ctor(); ! 328: if (ctor == 0) goto oper_coerce; ! 329: register Pfct f = Pfct(ctor->tp); ! 330: //error('d',"ctor %n f %t",ctor,f); ! 331: switch (f->base) { ! 332: case FCT: ! 333: switch (f->nargs) { ! 334: case 1: ! 335: one: ! 336: { Ptype tt = f->argtype->tp; ! 337: if (tt->check(t2,COERCE)==0) ! 338: val = 1; ! 339: else if (const_problem) { ! 340: Pptr p1 = tt->is_ptr_or_ref(); ! 341: if (p1==0 || p1->typ->tconst()) val = 1; ! 342: } ! 343: if (tt = tt->is_ref()) { ! 344: Pptr pt = t2->addrof(); // handle derived classed ! 345: tt->base = PTR; ! 346: if (tt->check(pt,COERCE) == 0) val = 1; ! 347: tt->base = RPTR; ! 348: delete pt; ! 349: } ! 350: goto oper_coerce; ! 351: } ! 352: default: ! 353: if (f->argtype->n_list->n_initializer) goto one; ! 354: case 0: ! 355: goto oper_coerce; ! 356: } ! 357: case OVERLOAD: ! 358: { register Plist gl; ! 359: ! 360: for (gl=Pgen(f)->fct_list; gl; gl=gl->l) { // look for match ! 361: Pname nn = gl->f; ! 362: Pfct ff = Pfct(nn->tp); ! 363: ! 364: switch (ff->nargs) { ! 365: case 0: ! 366: break; ! 367: case 1: ! 368: over_one: ! 369: { Ptype tt = ff->argtype->tp; ! 370: //error('d',"over one %t %t -> %d %d",tt,t2,tt->check(t2,COERCE),const_problem); ! 371: if (tt->check(t2,COERCE)==0) ! 372: val = 1; ! 373: else if (const_problem) { ! 374: Pptr p1 = tt->is_ptr_or_ref(); ! 375: if (p1==0 || p1->typ->tconst()) val = 1; ! 376: } ! 377: if (tt=tt->is_ref()) { ! 378: Pptr pt = t2->addrof(); // handle derived classed ! 379: tt->base = PTR; ! 380: if (tt->check(pt,COERCE) == 0) { ! 381: tt->base = RPTR; ! 382: delete pt; ! 383: val = 1; ! 384: goto oper_coerce; ! 385: } ! 386: tt->base = RPTR; ! 387: delete pt; ! 388: } ! 389: break; ! 390: } ! 391: default: ! 392: if (ff->argtype->n_list->n_initializer) goto over_one; ! 393: } ! 394: } ! 395: goto oper_coerce; ! 396: } ! 397: default: ! 398: error('i',"cannot_coerce(%k)\n",f->base); ! 399: } ! 400: } ! 401: ! 402: oper_coerce: ! 403: //error('d',"oper_coerce %d",val); ! 404: if (c2) { ! 405: Pclass cl = Pclass(c2->tp); ! 406: int std = 0; ! 407: int oval = val; ! 408: extern Pname conv_dominates(Pname,Pname); ! 409: for (Pname ox, on=cl->conv; on; on=ox) { ! 410: ox = on->n_list; ! 411: Plist gl = 0; ! 412: if ( on->tp->base == OVERLOAD ) { ! 413: gl = Pgen(on->tp)->fct_list; ! 414: on = gl->f; ! 415: gl = gl->l; ! 416: } ! 417: ! 418: overlist: ! 419: // error( 'd', "can coerce: on: %n tp: %t gl: %d", on, on->tp, gl ); ! 420: ! 421: Pfct f = Pfct(on->tp); ! 422: Nstd = 0; ! 423: if (t1->check(f->returns,COERCE) == 0) { ! 424: if (Nstd==0) { // forget solutions involving standard conversions ! 425: Pname old = Ncoerce; ! 426: if (std) { // forget ! 427: val = oval+1; ! 428: std = 0; ! 429: Ncoerce = on; ! 430: } ! 431: else if (Ncoerce == 0) { ! 432: // val = 1; ! 433: val++; ! 434: Ncoerce = on; ! 435: } ! 436: else if ((Ncoerce = conv_dominates(Ncoerce,on))==0) { ! 437: if (val == 1) { ! 438: //error('d',"val==1 on %n old %n",on,old); ! 439: Ptype ton = Pfct(on->tp)->returns; ! 440: Ptype tco = Pfct(old->tp)->returns; ! 441: if (t1->check(ton,0)==0) ! 442: ; ! 443: else if (t1->check(tco,0)==0) ! 444: on = old; ! 445: else ! 446: val++; ! 447: } ! 448: else ! 449: val++; ! 450: Ncoerce = on; ! 451: } ! 452: } ! 453: else { // take note only if no exact match seen ! 454: if (Ncoerce==0 || on->tp->check(Ncoerce->tp,0)) { ! 455: if (val==0 || std) { ! 456: ! 457: if (Ncoerce) Ncoerce = conv_dominates(Ncoerce,on); ! 458: if (Ncoerce == 0) { ! 459: Ncoerce = on; ! 460: val++; ! 461: std = 1; ! 462: } ! 463: } ! 464: } ! 465: } ! 466: } ! 467: // error( 'd', "can_coerce: gl: %d", gl ); ! 468: if ( gl ) { ! 469: on = gl->f; ! 470: gl = gl->l; ! 471: goto overlist; // must walk list of overloaded instances ! 472: } ! 473: } ! 474: } ! 475: //error('d',"val %d",val); ! 476: if (val) return val; ! 477: if (c1 && Pclass(c1->tp)->has_itor()) return 0; ! 478: //error('d',"%t->check(%t) -> %d",t1,t2,t1->check(t2,COERCE)); ! 479: if (t1->check(t2,COERCE)) return 0; ! 480: return 1; ! 481: } ! 482: ! 483: static const int NONE = 0; ! 484: static const int ELLIP = 1; ! 485: static const int UDC = 2; ! 486: static const int STD = 3; ! 487: static const int PROM = 4; ! 488: static const int EXACT = 5; ! 489: ! 490: inline int min(int i, int j) { return i<j ? i : j; } ! 491: ! 492: int matchable(Pname n, Pexpr arg, int constObj) ! 493: /* ! 494: look to see if the argument list "arg" can match a call of "n" ! 495: return worst kind of conversion done or NONE ! 496: */ ! 497: { ! 498: Pfct f = n->fct_type(); ! 499: register Pexpr e; ! 500: register Pname nn; ! 501: int worst = EXACT; //for compatibilty ! 502: ! 503: // if(template function) continue; ! 504: ! 505: if(constObj && n->n_oper!=CTOR && !f->f_const && !f->f_static) ! 506: return NONE; ! 507: ! 508: for(e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) { ! 509: if (nn == 0) return f->nargs_known==ELLIPSIS; ! 510: Pexpr a = e->e1; ! 511: Ptype at = a->tp; ! 512: if (exact1(nn,at)) {worst=min(worst,EXACT);continue;} ! 513: if (exact2(nn,at)) {worst=min(worst,PROM);continue;} ! 514: if (exact3(nn,at)) {worst=min(worst,STD);continue;} ! 515: if (!can_coerce(nn->tp,at)) return NONE; ! 516: else worst=UDC; ! 517: } ! 518: if (nn && (Ninit=nn->n_initializer)==0) return NONE; ! 519: return min(worst,EXACT); ! 520: } ! 521: ! 522: Pname Nover; ! 523: ! 524: int over_call(Pname n, Pexpr arg) ! 525: /* ! 526: return EXACT if n(arg) can be performed without coercion ! 527: return PROM if n(arg) can be performed only with promotion coercion ! 528: return STD if n(arg) can be performed only with standard coercion ! 529: return UDC if n(arg) can be performed only with user defined coercion ! 530: return 0 if n(arg) is an error ! 531: Nover is the function found, if any ! 532: Nstd is the number of standard coercions used ! 533: */ ! 534: { ! 535: register Plist gl; ! 536: Pgen g = Pgen(n->tp); ! 537: if (arg && arg->base!= ELIST) error('i',"ALX"); ! 538: ! 539: extern suppress_error; ! 540: suppress_error = 1; ! 541: Nstd = 0; ! 542: switch (g->base) { ! 543: default: error('i',"over_call(%t)\n",g); ! 544: case OVERLOAD: break; ! 545: case FCT: ! 546: //error('d',"over_call(%n) %k",n,n->tp->base); ! 547: Nover = n; ! 548: Ninit = 0; ! 549: int howGood = matchable(n,arg,0); ! 550: if(howGood <= UDC) Nstd = 0; ! 551: suppress_error = 0; ! 552: return howGood; ! 553: } ! 554: ! 555: Pname exact = 0; ! 556: int no_exact = 0; ! 557: int ret = 0; ! 558: Pname nret; ! 559: for (gl=g->fct_list; gl; gl=gl->l) { /* look for match */ ! 560: Nover = gl->f; ! 561: Ninit = 0; ! 562: Nstd = 0; ! 563: int howGood = matchable(Nover,arg,0); ! 564: if (howGood == EXACT) {suppress_error = 0; return EXACT; } ! 565: if (ret<PROM && howGood==PROM) { ! 566: nret = Nover; ! 567: ret = PROM; ! 568: } ! 569: if (ret<STD && Ninit==0 && howGood==STD) { ! 570: nret = Nover; ! 571: ret = STD; ! 572: } ! 573: } ! 574: ! 575: suppress_error = 0; ! 576: if (ret) { ! 577: Nover = nret; ! 578: return ret; ! 579: } ! 580: ! 581: Nover = 0; ! 582: for (gl=g->fct_list; gl; gl=gl->l) { /* look for coercion */ ! 583: Pname nn = gl->f; ! 584: if (matchable(nn,arg,0)) { ! 585: Nover = nn; ! 586: return UDC; ! 587: } ! 588: } ! 589: return 0; ! 590: ! 591: } ! 592: ! 593: Ptype expr::call_fct(Ptable tbl) ! 594: /* ! 595: check "this" call: ! 596: e1(e2) ! 597: e1->typ() and e2->typ() has been done ! 598: */ ! 599: { ! 600: Pfct f; ! 601: Pname fn; ! 602: int x; ! 603: int k; ! 604: Pname nn; ! 605: Pexpr e; ! 606: Ptype t; ! 607: Pexpr arg = e2; ! 608: Ptype t1 = e1?e1->tp:0; ! 609: int argno; ! 610: Pexpr etail = 0; ! 611: bit no_change = 0; ! 612: Pname no_virt = 0; // set if explicit qualifier was used: c::f() ! 613: Pname chk = 0; // set if visibility check is needed ! 614: // that is if function name might have been ! 615: // found without use of find_name() ! 616: int const_obj = 0; ! 617: ! 618: if (t1 == any_type) return any_type; ! 619: ! 620: switch (base) { ! 621: case CALL: ! 622: case G_CALL: break; ! 623: default: error('i',"call_fct(%k)",base); ! 624: } ! 625: ! 626: // error('d',"call %d %k %n arg %d",this,e1->base,e1->base==NAME?e1:0,arg); ! 627: if (t1 == 0) error('i',"call_fct(e1=%d,e1->tp=%t)",e1,t1); ! 628: if (arg && arg->base!=ELIST) error('i',"badAL%d%k",arg,arg->base); ! 629: ! 630: switch (e1->base) { ! 631: case NAME: ! 632: fn = Pname(e1); ! 633: switch (fn->n_oper) { ! 634: case 0: ! 635: case CTOR: ! 636: case DTOR: ! 637: case TYPE: ! 638: case NEW: ! 639: case DELETE: ! 640: break; ! 641: default: // real operator: check for operator+(1,2); ! 642: if (arg == 0) break; ! 643: Pexpr a = arg->e1; // first operand ! 644: ! 645: if (Pfct(fn->tp)->memof // obj.operator(1) is OK ! 646: || a->tp->is_cl_obj() ! 647: || a->tp->is_ref()) break; ! 648: a = arg->e2; ! 649: if (a == 0) // unary ! 650: error("%k of basicT",fn->n_oper); ! 651: else { // binary ! 652: a = a->e1; // second operand ! 653: if (a->tp->is_cl_obj() || a->tp->is_ref()) break; ! 654: error("%k of basicTs",fn->n_oper); ! 655: } ! 656: break; ! 657: } ! 658: break; ! 659: case REF: ! 660: case DOT: ! 661: no_virt = Pname(e1->n_initializer); ! 662: e1->n_initializer = 0; ! 663: if (e1 && e1->e1) { ! 664: Ptype t = e1->e1->tp; ! 665: Pptr tt = t->is_ptr_or_ref(); ! 666: Ptype ft = tt ? tt->typ : t; ! 667: Pexpr ee = e1->e1; ! 668: const_obj = ft->tconst(); ! 669: while (ee && (ee->base==DOT || ee->base==REF)) { ! 670: Pexpr m = ee->mem; ! 671: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 672: break; ! 673: ee = ee->e1; ! 674: } ! 675: if (ee) { ! 676: Ptype ttt = ee->tp; ! 677: int tc; ! 678: switch (e1->base) { ! 679: case REF: ! 680: Pptr p = ttt?ttt->is_ptr():0; ! 681: if (p && p->typ->tconst()) ! 682: const_obj = 1; ! 683: break; ! 684: case DOT: ! 685: tc = ttt ? ttt->tconst() : 0; ! 686: if(ttt && tc && (!strict_opt || tc!=2)) ! 687: const_obj = 1; ! 688: } ! 689: } ! 690: } ! 691: case MDOT: ! 692: { Pexpr n = e1->mem; ! 693: lxlx: ! 694: switch (n->base) { ! 695: case MDOT: ! 696: // reverse mdot (see expr::print()) ! 697: // p->a.b() => (&p->a)->b() => b(&p->a) ! 698: // or p->a->b() => (p->a)->b() => b(p->a) ! 699: // or oo.a.b() => (&oo.a)->b() => b(&oo.a) ! 700: // or oo.a->b() => (oo.a)->b() => b(oo.a) ! 701: { ! 702: Pexpr r = e1; ! 703: Pexpr p = r->e1; ! 704: for (Pexpr m = r->mem; m->base==MDOT; m = r->mem) { ! 705: p = new mdot(m->string2,p); ! 706: p->i1 = m->i1+2; ! 707: p->tp = p->mem->tp; ! 708: r->mem = m->mem; ! 709: r->e1 = p; ! 710: } ! 711: } ! 712: case REF: ! 713: case DOT: ! 714: n = n->mem; ! 715: goto lxlx; ! 716: case NAME: ! 717: break; ! 718: default: ! 719: error('i',"ref %k",n->base); ! 720: } ! 721: fn = Pname(n); ! 722: break; ! 723: } ! 724: case MEMPTR: ! 725: default: ! 726: fn = 0; ! 727: }; ! 728: ! 729: lll: ! 730: //error('d',"lll: %t %k",t1,t1->base); ! 731: switch (t1->base) { ! 732: case TYPE: ! 733: t1 = Pbase(t1)->b_name->tp; ! 734: goto lll; ! 735: ! 736: case PTR: // pf() allowed as shorthand for (*pf)() ! 737: switch (Pptr(t1)->typ->base) { ! 738: case FCT: ! 739: case OVERLOAD: ! 740: if (Pptr(t1)->memof) error("O missing in call throughP toMF"); ! 741: t1 = Pptr(t1)->typ; ! 742: fn = 0; ! 743: goto lll; ! 744: } ! 745: ! 746: default: ! 747: if (fn) ! 748: error("call of%n;%n is a%t",fn,fn,e1->tp); ! 749: else ! 750: error("call of%kE ofT%t",e1->base,e1->tp); ! 751: ! 752: case ANY: ! 753: return any_type; ! 754: ! 755: case OVERLOAD: ! 756: { ! 757: Pgen g = Pgen(t1); ! 758: Pname found = 0; ! 759: ! 760: // look for an exact match ! 761: found = g->exactMatch(arg,const_obj); ! 762: ! 763: // code for calls with template versions ! 764: /* ! 765: if(arg && !found && call to fn with template version) { ! 766: found = try_to_generate(arg); ! 767: } ! 768: */ ! 769: ! 770: // one argument in call: no need for intersect rule ! 771: if (!found && arg && arg->e2 == 0) { ! 772: found = g->oneArgMatch(arg,const_obj); ! 773: } ! 774: ! 775: // multiple arguments in call: potential need for ! 776: // intersect rule and simple rule ! 777: else if (!found) { ! 778: found = g->multArgMatch(arg,const_obj); ! 779: } ! 780: ! 781: // no functions are matchable ! 782: if (!found) { ! 783: Block(Pname) tmp(1); ! 784: tmp[0] = fn; ! 785: fmError(0,tmp,arg); ! 786: return any_type; ! 787: } ! 788: ! 789: overFound = chk = fn = found; ! 790: f = fn->fct_type(); ! 791: break; ! 792: } ! 793: case FCT: ! 794: f = Pfct(t1); ! 795: if (fn) { ! 796: switch (fn->n_oper) { ! 797: case CTOR: ! 798: case TYPE: ! 799: chk = fn; ! 800: } ! 801: } ! 802: } ! 803: ! 804: if (chk) { ! 805: Ptype t = 0; ! 806: Pexpr ee = e1->e1; ! 807: ! 808: switch (e1->base) { ! 809: case REF: // ptr->chk() ! 810: if (ee == 0) { // 0->x() fudge handling new x() ! 811: check_visibility(chk,no_virt,Pclass(chk->n_table->t_name->tp),tbl,cc->nof); ! 812: break; ! 813: }; ! 814: t = ee->tp->skiptypedefs(); ! 815: t = Pptr(t)->typ; ! 816: break; ! 817: case DOT: // obj.chk() ! 818: t = ee->tp; ! 819: } ! 820: ! 821: Pname cn = t?t->is_cl_obj():0; ! 822: Pclass cl = cn?Pclass(cn->tp):0; // class of ``this'' for chk ! 823: ! 824: if (cl) { ! 825: if (chk->n_oper==CTOR ! 826: && chk->n_protect ! 827: && cc->nof ! 828: && cc->nof->n_oper==CTOR) ! 829: // BUG: cannot handle protected base ! 830: // class constructor ! 831: ; ! 832: else { ! 833: check_visibility(chk,no_virt,cl,tbl,cc->nof); ! 834: } ! 835: } ! 836: } ! 837: ! 838: if (fn && f->returns->is_cl_obj() && f->f_result==0) { ! 839: // protect against class cn; cn f(); ... class cn { cn(cn&); ... }; ! 840: make_res(f); ! 841: f->returns->tsizeof(); // make sure it is declared ! 842: } ! 843: ! 844: //error('d',"fn %n %t printed %d",fn,fn?fn->tp:0,fn?fn->n_dcl_printed:0); ! 845: if (fn && fn->n_dcl_printed==0) { ! 846: if (f->f_inline==0 && f->f_imeasure) { ! 847: extern void uninline(Pname fn); ! 848: uninline(fn); ! 849: } ! 850: ! 851: // ensure printout of class declaration: ! 852: for (Pname nn=f->argtype; nn; nn=nn->n_list) ! 853: if (nn->tp->is_cl_obj()) (void) nn->tp->tsizeof(); ! 854: ! 855: fn->dcl_print(0); ! 856: } ! 857: ! 858: if (no_virt && f->f_static==0) { ! 859: if (e1->base==REF || e1->base==DOT) e1->n_initializer = fn; ! 860: } ! 861: else ! 862: fct_name = fn; ! 863: //error('d',"fn %n %t %d %d",fn,f,f->f_this,f->f_static); ! 864: if (f->f_this) { //SSS call of non-static memberfunction ! 865: switch (e1->base) { ! 866: case MEMPTR: ! 867: case REF: ! 868: case DOT: ! 869: break; ! 870: default: ! 871: error("O orP missing for%n ofT %t",fct_name,f); ! 872: } ! 873: } ! 874: else if (fn) { //SSS call of static function ! 875: sss: ! 876: switch (e1->base) { ! 877: case REF: ! 878: case DOT: ! 879: case MDOT: ! 880: e1 = e1->mem; ! 881: goto sss; ! 882: } ! 883: } ! 884: ! 885: if (fn) fn->use(); // a patch: ctors are sometimes not use()d ! 886: ! 887: if (f->f_const==0 ! 888: && (fn==0 || (fn->n_oper!=CTOR && fn->n_oper!=DTOR))) { //CCC ! 889: Pexpr ee = e1->e1; ! 890: // while (ee && (ee->base==DOT || ee->base==REF)) ee = ee->e1; ! 891: while (ee && (ee->base==DOT || ee->base==REF)) { ! 892: Pexpr m = ee->mem; ! 893: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 894: break; ! 895: ee = ee->e1; ! 896: } ! 897: // error('d', "ee: %k tp %k", ee?ee->base:0, ee?ee->tp->base:0); ! 898: ! 899: if (ee) { ! 900: Ptype tt = ee->tp; ! 901: switch (e1->base) { ! 902: case REF: ! 903: { Pptr p = tt?tt->is_ptr():0; ! 904: if (p && p->typ->tconst()) ! 905: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn); ! 906: // is really an error, but only warn to help transition ! 907: break; ! 908: } ! 909: case DOT: ! 910: int tc = tt ? tt->tconst() : 0; ! 911: if (tt && tc && (!strict_opt || tc!=2)) ! 912: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn); ! 913: // is really an error, but only warn to help transition ! 914: } ! 915: } ! 916: } ! 917: ! 918: t = f->returns; ! 919: x = f->nargs; ! 920: k = f->nargs_known; ! 921: ! 922: e = arg; ! 923: if (k == 0) goto rlab; ! 924: ! 925: for (nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) { ! 926: Pexpr a; ! 927: int save_base = 0; ! 928: char* save_name = 0; ! 929: ! 930: if (e) { ! 931: a = e->e1; ! 932: etail = e; ! 933: ! 934: if (nn) { /* type check */ ! 935: Ptype t1 = nn->tp->skiptypedefs(); ! 936: //error('d',"argtp %t etp %t a %k",t1,a->tp,a->base); ! 937: ! 938: switch (t1->base) { ! 939: case RPTR: ! 940: { Ptype pt = Pptr(t1)->typ; ! 941: if (pt->base != FCT || ! 942: ( pt->base == FCT && ! 943: pt->check(a->tp,0))) ! 944: a = ref_init(Pptr(nn->tp),a,tbl); ! 945: goto cbcb; ! 946: } ! 947: case COBJ: ! 948: if (a->base!=G_CM ! 949: || nn->tp->check(a->tp,ASSIGN)) ! 950: a = class_init(0,t1,a,tbl); ! 951: else ! 952: a->e2=class_init(0,t1,a->e2,tbl); ! 953: if (nn->n_xref) { ! 954: // (temp.ctor(arg),&arg) ! 955: a = a->address(); ! 956: } ! 957: else { ! 958: // defend against: ! 959: // int f(X); ... X(X&); ! 960: Pname cln = Pbase(t1)->b_name; ! 961: if (cln && Pclass(cln->tp)->has_itor()) { ! 962: // mark X(X&) arguments ! 963: nn->n_xref = 1; ! 964: a = a->address(); ! 965: } ! 966: } ! 967: cbcb: ! 968: //error('d',"cbcb: a %d %k %t",a->base,a->base,a->tp); ! 969: if (a->base==G_CM) { ! 970: if (a->e1->base==DEREF) a->e1 = a->e1->e2; // (*e1,e2) => (e1,e2) ! 971: if (a->e1->base==G_CALL ! 972: && Pname(a->e1->fct_name) ! 973: && Pname(a->e1->fct_name)->n_oper==CTOR ! 974: && (a->e2->base==G_ADDROF || a->e2->base==ADDROF)) { ! 975: a = a->e1; // (ctor(&tmp),&tmp) => ctor(&tmp) ! 976: goto cccc; ! 977: } ! 978: else if (a->e2->base==G_ADDROF ! 979: && a->e2->e2->base==NAME) { ! 980: cccc: ! 981: if (t1->base==RPTR ! 982: && Pptr(t1)->typ->tconst()==0) { // temporary used ! 983: if (warning_opt) ! 984: error('w',"temporary used for non-const%tA",nn->tp); ! 985: else { ! 986: Ptype atp = a->tp; ! 987: if (atp==void_type ! 988: && a->base==G_CALL ! 989: && a->e1->tp->base==FCT) ! 990: atp = Pfct(a->e1->tp)->s_returns; ! 991: ! 992: Ptype tt = t1->is_ref(); ! 993: //error('d',"tt %t atp %t",tt,atp); ! 994: if (tt) { ! 995: if (Pptr(tt)->typ->tsizeof()!=atp->tsizeof()) { // sliced ! 996: Ptype aat = atp->is_ptr_or_ref(); ! 997: if (aat==0 ! 998: || Pptr(tt)->typ->tsizeof()!=Pptr(aat)->typ->tsizeof()) ! 999: error('w',"temporary used for non-const%tA",nn->tp); ! 1000: } ! 1001: } ! 1002: else if (t1->tsizeof()!=atp->tsizeof()) // sliced ! 1003: error('w',"temporary used for non-const%tA",nn->tp); ! 1004: } ! 1005: ! 1006: } ! 1007: } ! 1008: } ! 1009: e->e1 = a; ! 1010: break; ! 1011: case ANY: ! 1012: goto rlab; ! 1013: case PTR: ! 1014: { ! 1015: save_base = e->e1->base; ! 1016: if(a->tp->base==OVERLOAD) ! 1017: save_name = Pgen(a->tp)->fct_list->f->string; ! 1018: Pexpr te_a = a; ! 1019: e->e1 = a = ptr_init(Pptr(t1),a,tbl); ! 1020: no_change = (te_a == a); ! 1021: if (Pchecked == 0) goto def; ! 1022: break; ! 1023: } ! 1024: case CHAR: ! 1025: case SHORT: ! 1026: case INT: ! 1027: { Ptype t = a->tp->skiptypedefs(); ! 1028: switch (t->base) { ! 1029: case LONG: ! 1030: case FLOAT: ! 1031: case DOUBLE: ! 1032: case LDOUBLE: ! 1033: error('w',"A%d: %t passed as %t",argno,a->tp,t1); ! 1034: } ! 1035: } ! 1036: // no break ! 1037: case LONG: ! 1038: if (Pbase(t1)->b_unsigned ! 1039: && a->base==UMINUS ! 1040: && a->e2->base==ICON) ! 1041: error('w',"negativeA for%n, unsignedX",fn); ! 1042: default: ! 1043: def: ! 1044: { Pexpr x = try_to_coerce(t1,a,"argument",tbl); ! 1045: //error('d',"x %d t1 %t nn %t a1 %t",x,t1,nn->tp,a->tp); ! 1046: if (x) { ! 1047: if (Pchecked == 0 && no_change) { ! 1048: Pexpr te_x = ptr_init(Pptr(t1), x, tbl); ! 1049: ! 1050: if ( te_x != x ) e->e1 = a = te_x; else e->e1=x; ! 1051: } ! 1052: else ! 1053: e->e1 = x; ! 1054: } ! 1055: else if (nn->tp->check(a->tp,ARG)) { ! 1056: error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp); ! 1057: return any_type; ! 1058: } ! 1059: } ! 1060: } ! 1061: ! 1062: Pexpr tt = e->e1; ! 1063: while ( tt->base == CAST ) ! 1064: tt = tt->e1; ! 1065: if ( tt->base == ILIST ) ! 1066: e->e1 = tt; ! 1067: ! 1068: if (e->e1->base == ILIST) { ! 1069: // memptr constant ! 1070: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 1071: if(save_base == REF) { ! 1072: Pptr m = Pptr(a->tp); ! 1073: error(strict_opt?0:'w', ! 1074: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)", ! 1075: m->memof->string, ! 1076: m->memof->string, ! 1077: save_name ! 1078: ); ! 1079: } ! 1080: Pname temp = make_tmp('A',mptr_type,tbl); ! 1081: e->e1 = mptr_assign(temp,e->e1); ! 1082: e->e1 = a = new expr(G_CM,e->e1,temp); ! 1083: a->tp = temp->tp; ! 1084: } ! 1085: ! 1086: } ! 1087: else { ! 1088: if (k != ELLIPSIS) { ! 1089: error("unexpected %dA for%n",argno,fn); ! 1090: return any_type; ! 1091: } ! 1092: Pexpr te=e; ! 1093: while(e) { ! 1094: if (e->e1->base == ILIST) { ! 1095: // memptr constant ! 1096: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 1097: Pname temp = make_tmp('A',mptr_type,tbl); ! 1098: e->e1 = mptr_assign(temp,e->e1); ! 1099: e->e1 = a = new expr(G_CM,e->e1,temp); ! 1100: a->tp = temp->tp; ! 1101: } ! 1102: e = e->e2; ! 1103: } ! 1104: e = te; ! 1105: goto rlab; ! 1106: } ! 1107: } ! 1108: else { /* default argument? */ ! 1109: a = nn->n_initializer; ! 1110: if (a == 0) { ! 1111: error("A %d ofT%tX for%n",argno,nn->tp,fn); ! 1112: return any_type; ! 1113: } ! 1114: if (a->base == ILIST) { ! 1115: // memptr constant ! 1116: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 1117: Pname temp = make_tmp('A',mptr_type,tbl); ! 1118: a = mptr_assign(temp,a); ! 1119: a = new expr(G_CM,a,temp); ! 1120: a->tp = temp->tp; ! 1121: } ! 1122: a->permanent = 2; // ought not be necessary, but it is ! 1123: e = new expr(ELIST,a,0); ! 1124: if (etail) ! 1125: etail->e2 = e; ! 1126: else ! 1127: e2 = e; ! 1128: etail = e; ! 1129: } ! 1130: } ! 1131: ! 1132: rlab: ! 1133: //error('d',"rlab fct_name %n %t",fct_name,fct_name?fct_name->tp:0); ! 1134: for (; e; e = e->e2) { // unchecked arguments ! 1135: Pexpr a = e->e1; ! 1136: Pname cn; ! 1137: ! 1138: if (a->base==NAME && a->tp->base==FCT) { ! 1139: // function name that escaped the type system: ! 1140: // update use count ! 1141: a->lval(ADDROF); ! 1142: } ! 1143: else if (warning_opt && (cn = a->tp->is_cl_obj())) { ! 1144: Pclass cl = Pclass(cn->tp); ! 1145: if (cl->has_ctor() || cl->memtbl->look("__as",0))//cl->has_oper(ASSIGN) ! 1146: { ! 1147: if (fct_name) ! 1148: error('w',"O ofC%t withK or = copied asA to%n (%t)",cl,fct_name,fct_name->tp); ! 1149: else ! 1150: error('w',"O ofC%t withK or = copied asA to `...'",cl); ! 1151: } ! 1152: } ! 1153: else if (a->tp->is_ref()) ! 1154: e->e1 = a->contents(); ! 1155: } ! 1156: ! 1157: if (f->f_result) { // f(args) => (f(&temp,args),temp) ! 1158: Pname tn = make_tmp('R',f->returns,tbl); ! 1159: e2 = new expr(ELIST,tn->address(),e2); ! 1160: Pexpr ee = new expr(0,0,0); ! 1161: *ee = *this; ! 1162: base = G_CM; // (f(&temp,args),temp) ! 1163: e1 = ee; ! 1164: if (refd == 2) ! 1165: e2 = tn->address(); ! 1166: else e2 = tn; ! 1167: tp = tn->tp; ! 1168: } ! 1169: ! 1170: return t; ! 1171: } ! 1172: ! 1173: int cm_const_save; ! 1174: ! 1175: Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl) ! 1176: /* ! 1177: initialize the "p" with the "init" ! 1178: remember to call ptr_init to ensure that pointers to second bases ! 1179: are handled correctly. ! 1180: */ ! 1181: { ! 1182: register Ptype it = init->tp->skiptypedefs(); ! 1183: Pptr px = Pptr(p->skiptypedefs()); ! 1184: Ptype p1 = px->typ->skiptypedefs(); ! 1185: Pname c1 = p1->is_cl_obj(); ! 1186: // error('d',"ref_init: p %t, p1 %t, px %t, init->tp %t",p,p1,px,it); ! 1187: // error('d', "ref_init: nof: %n f_const: %d", cc?cc->nof:0, cc?(cc->nof?Pfct(cc->nof->tp)->f_const:0):0); ! 1188: ! 1189: if (init->base == ILIST) error("IrL as RIr"); ! 1190: ! 1191: if (init->base==NAME ! 1192: && Pname(init)->n_scope==ARG ! 1193: && init->tp->base==FLOAT) ! 1194: error('w',"initializing a float& with floatA is non-portable"); ! 1195: ! 1196: switch (it->base) { ! 1197: default: ! 1198: { Ptype tt = it->addrof(); ! 1199: px->base = PTR; // allow &x for y& when y : public x ! 1200: // but not &char for int& ! 1201: int x = px->check(tt,COERCE); ! 1202: ! 1203: if (x == 0) { //CCC type is fine check for constness: ! 1204: if (init->tp->tconst() ! 1205: && vec_const==0 ! 1206: && fct_const==0) { ! 1207: // not ``it'' ! 1208: if (init->base == ELIST) init = init->e1; ! 1209: if (px->typ->tconst() == 0) error("R to constO"); ! 1210: px->base = RPTR; ! 1211: // if we have a const lvalue we can still pass its address ! 1212: ignore_const++; ! 1213: if (init->lval(0)) { ! 1214: init->lval(ADDROF); // force output ! 1215: ignore_const--; ! 1216: //error('d',"in1 %t",init->tp); ! 1217: return ptr_init(px,init->address(),tbl);//return init->address(); ! 1218: } ! 1219: ignore_const--; ! 1220: goto xxx; ! 1221: } ! 1222: px->base = RPTR; ! 1223: if (init->lval(0)) { // can pass the address // no temporary needed ! 1224: init->lval(ADDROF); // force output ! 1225: //error('d',"px %t init %t init %t",px,init->tp,init->tp); ! 1226: return ptr_init(px,init->address(),tbl); ! 1227: } ! 1228: goto xxx; ! 1229: } ! 1230: ! 1231: px->base = RPTR; ! 1232: } ! 1233: } ! 1234: ! 1235: //error('d',"c1 %n",c1); ! 1236: if (c1) { // assigning to a const X & is fine ! 1237: ref_cast++; ! 1238: Pexpr x = try_to_coerce(p,init,"reference initialization",tbl); ! 1239: ref_cast--; ! 1240: if (x) { ! 1241: init = x; ! 1242: goto xxx; ! 1243: } ! 1244: int bc = Pbase(p1)->b_const; ! 1245: Pbase(p1)->b_const = 0; ! 1246: // refd = 1; ! 1247: switch ( init->base ) { ! 1248: case STRING: case ZERO: case CCON: ! 1249: case ICON: case FCON: case IVAL: ! 1250: case NAME: ! 1251: refd = 1; ! 1252: break; ! 1253: default: ! 1254: refd = (init->e1 && init->e1->base == NAME && ! 1255: init->e1->tp->base != RPTR && ! 1256: Pname(init->e1)->n_xref == 0) ? 2: 1; ! 1257: break; ! 1258: } ! 1259: // error('d', "***** refd: %d", refd ); ! 1260: Pexpr a = class_init(0,p1,init,tbl); ! 1261: Pbase(p1)->b_const = bc; ! 1262: refd = 0; ! 1263: if (a==init && init->tp!=any_type) goto xxx; ! 1264: // error('d',"ri a %d %k",a->base,a->base); ! 1265: switch (a->base) { ! 1266: case G_CALL: ! 1267: init = a; ! 1268: goto xxx; ! 1269: } ! 1270: a = a->address(); ! 1271: a = ptr_init(px,a,tbl); ! 1272: return a; ! 1273: } ! 1274: ! 1275: //error('d',"p1 %t it %t",p1,it); ! 1276: if (p1->check(it,0)) { ! 1277: ! 1278: if (p1->check(it,ASSIGN) == 0) { ! 1279: // things like ``double& rr = 1;'' temporary needed ! 1280: // warn in case of ``slightly wrong lvalue'', e.g. ! 1281: // int i; double& r = i; ! 1282: if (init->lval(0) && p1->tconst()==0) ! 1283: error('w',"temporary used toIR; no changes will be propagated to actualA"); ! 1284: goto def; ! 1285: } ! 1286: ! 1287: Pexpr x = try_to_coerce(p1,init,"reference",tbl); // x==init ! 1288: if (x==0) x = try_to_coerce(px,init,"reference",tbl); // x&=init ! 1289: if (x) { ! 1290: init = x; ! 1291: goto def; ! 1292: } ! 1293: ! 1294: error("badIrT:%t (%tX)",it,p); ! 1295: if (init->base != NAME) init->tp = any_type; ! 1296: return init; ! 1297: } ! 1298: ! 1299: xxx: /* ! 1300: here comes the test of a ``fundamental theorem'': ! 1301: a structure valued expression is ! 1302: (1) an lvalue of type T (possibly const) ! 1303: or (2) the result of a function (a _result if X(X&) is defined) ! 1304: or (3) a * or [] or ? or , expression ! 1305: */ ! 1306: //error('d',"xxx %k %d %t",init->base,init->base,init->tp); ! 1307: ! 1308: switch (init->base) { ! 1309: case NAME: ! 1310: case DEREF: ! 1311: case REF: ! 1312: case DOT: // init => &init ! 1313: if (it->tconst() && vec_const==0 && fct_const==0) goto def; ! 1314: if ( cc && cc->nof && ! 1315: Pfct(cc->nof->tp)->f_const ) ! 1316: cm_const_save = Pbase(p->typ)->b_const; ! 1317: init->lval(ADDROF); ! 1318: cm_const_save = 0; ! 1319: ! 1320: if (vec_const) return init; ! 1321: if (fct_const && p1->is_ptr()) goto def; // fptr& = fct ! 1322: // no break ! 1323: case CM: ! 1324: case G_CM: // & (f(&temp), temp) ! 1325: return ptr_init(px,init->address(),tbl);//init->address(); ! 1326: default: ! 1327: def: ! 1328: { ! 1329: // error('d',"def: init->tp %t p1 %t ",init->tp,p1); ! 1330: // error('d',"p1: %t const_ptr: %d", p1, const_ptr); ! 1331: if (const_ptr == 0) { ! 1332: if (tbl == gtbl || strict_opt) ! 1333: error("Ir for%snon-constR not an lvalue", strict_opt?"":" global "); ! 1334: else ! 1335: if (warning_opt) ! 1336: error('w', "Ir for non-constR not an lvalue (anachronism)"); ! 1337: } ! 1338: ! 1339: Pname tcl = p1->is_cl_obj (); ! 1340: if(tcl && Pclass(tcl->tp)->c_abstract) ! 1341: error("a temporary is needed for a parameter, but the argument type is abstract class %t.", tcl->tp); ! 1342: ! 1343: Pname n = make_tmp('I',p1,tbl); ! 1344: Pexpr a; ! 1345: Pname ic = init->tp->is_cl_obj(); ! 1346: ! 1347: if (p1->tconst()==0 ! 1348: && (init->tp->tconst() && vec_const==0 && fct_const==0) ! 1349: && p1->check(it,ASSIGN)==0) ! 1350: error('w',"constIr: temporary used toI reference"); ! 1351: ! 1352: switch (p1->base) { ! 1353: case INT: ! 1354: case CHAR: ! 1355: case SHORT: ! 1356: switch (it->base) { ! 1357: case LONG: ! 1358: case FLOAT: ! 1359: case DOUBLE: ! 1360: case LDOUBLE: ! 1361: error('w',"%t assigned to %t inRIr",it,p1); ! 1362: } ! 1363: } ! 1364: ! 1365: if (ic!=c1 && Pclass(ic->tp) != Pclass(c1->tp)) { ! 1366: // derived class1 => must cast: ``it Ix; (Ix=init,(p)&Ix);'' ! 1367: n->tp = init->tp; ! 1368: a = ptr_init(px,n->address(),tbl);//n->address(); ! 1369: PERM(p); ! 1370: a = new texpr(CAST,p,a); ! 1371: a->tp = p; ! 1372: } ! 1373: else ! 1374: a = n->address(); ! 1375: ! 1376: refd = 1; ! 1377: Pexpr as = init_tmp(n,init,tbl); ! 1378: refd = 0; ! 1379: a = new expr(G_CM,as,a); ! 1380: a->tp = a->e2->tp; ! 1381: return a; ! 1382: } ! 1383: } ! 1384: } ! 1385: ! 1386: Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl) ! 1387: /* ! 1388: initialize "nn" of type "tt" with "init" ! 1389: if nn==0 make a temporary, ! 1390: nn may not be a name ! 1391: */ ! 1392: { ! 1393: if (init == dummy) return 0; ! 1394: //error('d',"class_init %t with %t init %k refd %d",tt,init->tp,init->base,refd); ! 1395: Pname c1 = tt->is_cl_obj(); ! 1396: ! 1397: if (init == 0) { ! 1398: error("emptyIr"); ! 1399: return dummy; ! 1400: } ! 1401: ! 1402: if (c1) { ! 1403: Pclass cl = Pclass(c1->tp); ! 1404: Pname c2 = init->tp->is_cl_obj(); ! 1405: ! 1406: if (c1!=c2 || (refd==0 && cl->has_itor())) { ! 1407: /* really ought to make a temp if refd, ! 1408: but ref_init can do that ! 1409: */ ! 1410: int i = can_coerce(tt,init->tp); ! 1411: //error('d',"i %d nn %n",i,nn); ! 1412: switch (i) { ! 1413: default: ! 1414: error("%d ways of making a%n from a%t",i,c1,init->tp); ! 1415: init->tp = any_type; ! 1416: return init; ! 1417: case 0: ! 1418: if (c2 && Pclass(c2->tp)->has_base(cl)) { ! 1419: init = init->address(); ! 1420: Pexpr x = cast_cptr(cl,init,tbl,0); ! 1421: ! 1422: if (x == init) { ! 1423: Ptype pt = tt->addrof(); ! 1424: PERM(pt); ! 1425: x = new cast(pt,init); ! 1426: } ! 1427: ! 1428: return x->contents(); ! 1429: } ! 1430: error("cannot make a%n from a%t",c1,init->tp); ! 1431: init->tp = any_type; ! 1432: return init; ! 1433: case 1: ! 1434: //error('d',"ncoerce %n %k %d",Ncoerce,init->base,init->base); ! 1435: if (Ncoerce == 0) { ! 1436: Pexpr a = new expr(ELIST,init,0); ! 1437: a = new texpr(VALUE,tt,a); ! 1438: a->e2 = nn; ! 1439: a = a->typ(tbl); ! 1440: //error('d',"ci a %k %d %t",a->base,a->base,a->tp); ! 1441: return a; ! 1442: } ! 1443: ! 1444: switch (init->base) { ! 1445: case CM: ! 1446: case G_CM: //ddd ! 1447: case NAME: /* init.coerce() */ ! 1448: /* *ref */ case DEREF: ! 1449: { Pref r = new ref(DOT,init,Ncoerce); ! 1450: Pexpr rr = r->typ(tbl); ! 1451: init = new expr(G_CALL,rr,0); ! 1452: init->fct_name = Ncoerce; ! 1453: break; ! 1454: } ! 1455: default: // (temp=init,temp.coerce()) ! 1456: { Pname tmp = make_tmp('U',init->tp,tbl); ! 1457: int x = refd; ! 1458: refd = 0; // ?? ! 1459: Pexpr ass = init_tmp(tmp,init,tbl); ! 1460: refd = x; ! 1461: Pref r = new ref(DOT,tmp,Ncoerce); ! 1462: Pexpr rr = r->typ(tbl); ! 1463: Pexpr c = new expr(G_CALL,rr,0); ! 1464: c->fct_name = Ncoerce; ! 1465: c = c->typ(tbl); ! 1466: init = new expr(CM,ass,c); ! 1467: init->tp = c->tp; ! 1468: if (refd) { // &f() => (t=f(), &t) ! 1469: Pname tmp2 = make_tmp('L',c->tp,tbl); ! 1470: ass = init_tmp(tmp2,init,tbl); ! 1471: init = new expr(G_CM,ass,tmp2); ! 1472: } ! 1473: } ! 1474: } ! 1475: //error('d',"nn %n",nn); ! 1476: if (nn) { ! 1477: Pexpr a = new expr(ELIST,init,0); ! 1478: a = new texpr(VALUE,tt,a); ! 1479: a->e2 = nn; ! 1480: return a->typ(tbl); ! 1481: } ! 1482: } ! 1483: //error('d',"c1 %n c2 %n",c1,c2); ! 1484: return init->typ(tbl); ! 1485: } ! 1486: return init; ! 1487: } ! 1488: //error('d',"ci check tt %t init->tp %t",tt,init->tp); ! 1489: if (tt->check(init->tp,ASSIGN) && refd==0) { ! 1490: error("badIrT:%t (%tX)",init->tp,tt); ! 1491: init->tp = any_type; ! 1492: } ! 1493: ! 1494: return init; ! 1495: } ! 1496: ! 1497: extern int bound; // fudge for bound pointers to functions ! 1498: ! 1499: Pexpr expr::docast(Ptable tbl) ! 1500: { ! 1501: // check cast against value, INCOMPLETE ! 1502: ! 1503: //error('d',"docast %d %t %k",this,tp2,e1->base); ! 1504: if (e1 == dummy) { ! 1505: error("E missing for cast"); ! 1506: tp = any_type; ! 1507: return this; ! 1508: } ! 1509: ! 1510: int pmf = 0; ! 1511: int ptom_cast = 0; ! 1512: Pexpr ee = e1; ! 1513: ! 1514: //error('d',"ee %k %d",ee->base,ee->base); ! 1515: switch (ee->base) { ! 1516: case ADDROF: ! 1517: ee = ee->e2; ! 1518: switch (ee->base) { ! 1519: case NAME: goto nm; ! 1520: case REF: goto rf; ! 1521: } ! 1522: break; ! 1523: ! 1524: case NAME: ! 1525: nm: ! 1526: if (Pname(ee)->n_qualifier) pmf = 1; ! 1527: break; ! 1528: ! 1529: case REF: ! 1530: rf: ! 1531: if (ee->e1->base == THIS) bound = 1; ! 1532: break; ! 1533: } ! 1534: ! 1535: e1 = e1->typ(tbl); ! 1536: ! 1537: int b = bound; // distinguish between explicit and implicit THIS ! 1538: bound = 0; ! 1539: //pmf = pmf && e1->base==CAST; ! 1540: pmf = pmf && (e1->base==CAST || e1->base==ILIST); ! 1541: ! 1542: Ptype etp = e1->tp->skiptypedefs(); ! 1543: Ptype tt = tp2; ! 1544: Ptype t = tt; ! 1545: tt->dcl(tbl); ! 1546: ! 1547: tt = tt->skiptypedefs(); ! 1548: ! 1549: //error('d',"e1 %k etp %t tt %t",e1->base,etp,tt); ! 1550: ! 1551: switch (etp->base) { ! 1552: case PTR: ! 1553: case RPTR: ! 1554: if (Pptr(etp)->typ->base == OVERLOAD) goto over; ! 1555: ! 1556: if (warning_opt && i2==0 && Pptr(etp)->typ->tconst()) { ! 1557: switch (tt->base) { ! 1558: case FCT: ! 1559: break; ! 1560: case PTR: ! 1561: case RPTR: ! 1562: if (Pptr(tt)->typ->tconst()) break; ! 1563: default: ! 1564: // casting away const ! 1565: // should be an error ! 1566: // but ANSI says OK so I chicken out ! 1567: // to be able to compile strtok(), etc. ! 1568: error('w',"const cast away:%t->%t",e1->tp,tp2); ! 1569: } ! 1570: } ! 1571: else ! 1572: i2 = 0; // to allow cfront to escape its own checking ! 1573: break; ! 1574: case COBJ: ! 1575: { ref_cast = 1; ! 1576: Pexpr x = try_to_coerce(tt,e1,"cast",tbl); ! 1577: ref_cast = 0; ! 1578: //error('d',"x %k %t tt %d %t",x?x->base:0,x?x->tp:0,tt,tt); ! 1579: if (x) { ! 1580: if (x!=e1 && x->base==DEREF && tt->is_ref()) x = x->e1; ! 1581: if (tt==x->tp || tt->check(x->tp,0)==0 || const_problem) ! 1582: return x; ! 1583: else ! 1584: return new cast(tt,x); ! 1585: } ! 1586: break; ! 1587: } ! 1588: case VOID: ! 1589: if (tt->base == VOID) { ! 1590: tp = t; ! 1591: return this; ! 1592: } ! 1593: error("cast of void value"); ! 1594: // no break; ! 1595: case ANY: ! 1596: any: ! 1597: tp = any_type; ! 1598: return this; ! 1599: case FCT: ! 1600: if (tt->base == PTR && Pptr(tt)->typ->base != FCT) ! 1601: error('w',"P toF cast toP to nonF"); ! 1602: break; ! 1603: case OVERLOAD: ! 1604: over: ! 1605: error("cast of overloaded"); ! 1606: goto any; ! 1607: } ! 1608: ! 1609: //error('d',"tt %t",tt); ! 1610: switch (tt->base) { ! 1611: case PTR: ! 1612: if (Pptr(tt)->typ->base==FCT && Pptr(tt)->memof) { ! 1613: if (etp->base!=PTR ! 1614: || Pptr(etp)->typ->base!=FCT ! 1615: || Pptr(etp)->memof==0) ! 1616: error("cast toP toM %t",tt); ! 1617: else { // adjust delta in MI case ! 1618: // for the moment just suppress the cast ! 1619: // all pmfs are the same to cc ! 1620: /* ! 1621: Pclass c1 = Pptr(tt)->memof; ! 1622: Pclass c2 = Pptr(etp)->memof; ! 1623: */ ! 1624: ptom_cast = 1; ! 1625: tp2 = void_type; ! 1626: } ! 1627: } ! 1628: ! 1629: switch (etp->base) { ! 1630: case COBJ: ! 1631: error("cannot castCO toP"); ! 1632: break; ! 1633: case FCT: ! 1634: e1 = new expr(G_ADDROF,0,e1); ! 1635: bound = b; ! 1636: e1 = e1->typ(tbl); ! 1637: bound = 0; ! 1638: if (e1->base == CAST) ! 1639: pmf = 1; ! 1640: else ! 1641: break; ! 1642: // no break; ! 1643: ! 1644: case PTR: ! 1645: { Pname cn = Pptr(tt)->typ->is_cl_obj(); ! 1646: if (cn) { ! 1647: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1); ! 1648: ! 1649: if (x == e1) { ! 1650: PERM(tt); ! 1651: e1 = new cast(tt,e1); ! 1652: e1->i2 = i2; ! 1653: } ! 1654: else ! 1655: e1 = x; ! 1656: } ! 1657: if (pmf) { ! 1658: tt = tt->skiptypedefs(); ! 1659: ! 1660: switch (tt->base) { ! 1661: case PTR: ! 1662: if (Pptr(tt)->memof) break; ! 1663: default: ! 1664: error("%t cast to%t (%t is not aP toM)",e1->tp,tp2,tp2); ! 1665: } ! 1666: } ! 1667: } ! 1668: } ! 1669: break; ! 1670: ! 1671: case RPTR: // (x&)e: pretend e is an x ! 1672: { Ptype er = etp; ! 1673: Ptype cr = tt; ! 1674: do { ! 1675: if (er = er->is_ptr_or_ref()) er = Pptr(er)->typ; ! 1676: if (cr = cr->is_ptr_or_ref()) cr = Pptr(cr)->typ; ! 1677: } while (er && cr); ! 1678: int pp = er!=0; // if `e' is a suitable pointer cast it: ! 1679: // (x&)e => (x*)e, otherwise ! 1680: // (x&)e => *(x*)&e ! 1681: // error('d',"rptr tt %t e1->base %k e1->tp %t",tt,e1->base,e1->tp); ! 1682: if (e1->base==G_CM ! 1683: || e1->base==CALL ! 1684: || e1->base==G_CALL ! 1685: || e1->lval(0)) ! 1686: ; ! 1687: else if (e1->tp->tconst()) { ! 1688: // casting away const ! 1689: // should be an error ! 1690: // but ANSI says OK so I chicken out ! 1691: // to be able to compile strtok(), etc. ! 1692: if (warning_opt && Pptr(tt)->typ->tconst()==0) ! 1693: error('w',"const cast away:%t->%t",e1->tp,tp2); ! 1694: ! 1695: } ! 1696: else ! 1697: error("cannot cast%t to%t",etp,t); ! 1698: //error('d',"e1 %k %t %d",e1->base,e1->tp,pp); ! 1699: if (pp == 0) e1 = e1->address(); // *(x*)&e ! 1700: tp = t; ! 1701: ! 1702: // do proper pointer manipulation for multiple inheritance ! 1703: Pname cn = Pptr(tt)->typ->is_cl_obj(); ! 1704: if (cn) { ! 1705: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1); ! 1706: ! 1707: if (x == e1) { ! 1708: PERM(tt); ! 1709: e1 = new cast(tt,e1); ! 1710: e1->i2 = i2; ! 1711: } ! 1712: else ! 1713: e1 = x; ! 1714: } ! 1715: ! 1716: return pp ? this : contents(); ! 1717: } ! 1718: case COBJ: ! 1719: base = VALUE; // (x)e => x(e): construct an x from e ! 1720: e1 = new expr(ELIST,e1,0); ! 1721: return typ(tbl); ! 1722: ! 1723: case CHAR: ! 1724: case INT: ! 1725: case SHORT: ! 1726: case LONG: ! 1727: switch (etp->base) { ! 1728: case FCT: ! 1729: e1 = new expr(ADDROF,0,e1); ! 1730: e1 = e1->typ(tbl); ! 1731: case PTR: ! 1732: if(!e1->tp->memptr() && e1->tp->tsizeof()>tt->tsizeof()) ! 1733: error("type ``%t'' not large enough for values of ``%t ''",tt,etp); ! 1734: break; ! 1735: case COBJ: ! 1736: error("cannot castCO to%k",tt->base); ! 1737: break; ! 1738: } ! 1739: break; ! 1740: ! 1741: case FLOAT: ! 1742: case DOUBLE: ! 1743: case LDOUBLE: ! 1744: switch (etp->base) { ! 1745: case FLOAT: ! 1746: case DOUBLE: ! 1747: case LDOUBLE: ! 1748: case CHAR: ! 1749: case INT: ! 1750: case SHORT: ! 1751: case LONG: ! 1752: case EOBJ: ! 1753: case ZTYPE: ! 1754: break; ! 1755: default: ! 1756: error("cannot cast ``%t '' to ``%t''",etp,tt); ! 1757: break; ! 1758: } ! 1759: break; ! 1760: ! 1761: case FCT: ! 1762: error("cannot cast toFT"); ! 1763: break; ! 1764: } ! 1765: ! 1766: tp = t; ! 1767: ! 1768: if (e1->base==ILIST && ptom_cast==0) { // pointer to member constant ! 1769: Pexpr ee = e1->e1; // ELIST ! 1770: int i; ! 1771: switch (ee->e2->base) { ! 1772: case IVAL: ! 1773: i = int(ee->e2->i1); ! 1774: break; ! 1775: case ZERO: ! 1776: i = 0; ! 1777: } ! 1778: ! 1779: if (i<0) ! 1780: e1 = e1->e2; // just the function ! 1781: else ! 1782: e1 = ee->e2; // just the index ! 1783: return this; ! 1784: } ! 1785: ! 1786: if (etp->base==PTR && Pptr(etp)->memof && Pptr(etp)->typ->base==FCT) { ! 1787: Pclass cl = Pptr(etp)->memof; ! 1788: ! 1789: if (Pptr(tt)->memof==0 && b == 0 ) { ! 1790: Pexpr y = new mdot("f",e1); ! 1791: y->i1 = 9; ! 1792: y = new cast(tt,y); ! 1793: if (cl->virt_count && b==0) { ! 1794: // ERROR: no check for side effects ! 1795: Pexpr z = new mdot("i",e1); ! 1796: Pexpr x = new mdot("i",e1); ! 1797: x->i1 = 9; ! 1798: x = new cast(tt,x); ! 1799: z->i1 = 9; ! 1800: Pexpr q = new expr (QUEST,x,y); ! 1801: q->cond = new expr(LE,zero,z); ! 1802: q->tp = tt; ! 1803: delete this; ! 1804: return q; ! 1805: } ! 1806: delete this; ! 1807: return y; ! 1808: } ! 1809: } ! 1810: ! 1811: return this; ! 1812: } ! 1813: ! 1814: Pexpr expr::dovalue(Ptable tbl) ! 1815: { ! 1816: Ptype tt = tp2; ! 1817: Pclass cl; ! 1818: Pname cn; ! 1819: ! 1820: //error('d',"value %d %t e1 %d e2 %d",tt,tt,e1,e2); ! 1821: ! 1822: tt->dcl(tbl); ! 1823: ! 1824: tt = tt->skiptypedefs(); ! 1825: ! 1826: switch (tt->base) { ! 1827: case EOBJ: ! 1828: default: ! 1829: if (e1 == 0) { ! 1830: error("value missing in conversion to%t",tt); ! 1831: return dummy; ! 1832: } ! 1833: base = CAST; ! 1834: e1 = e1->e1; // strip ELIST ! 1835: return typ(tbl); ! 1836: ! 1837: case CLASS: ! 1838: cl = Pclass(tt); ! 1839: tp2 = Pptr(cl->this_type)->typ; ! 1840: break; ! 1841: ! 1842: case COBJ: ! 1843: cn = Pbase(tt)->b_name; ! 1844: cl = Pclass(cn->tp); ! 1845: } ! 1846: ! 1847: //error('d',"e1 %k e1->e2 %k",e1->base,e1?e1->e2->base:0); ! 1848: if (e1 && e1->e2==0) { // single argument ! 1849: if (e1->e1->base==ELIST) e1->e1 = e1->e1->e1; // spurious elist ! 1850: e1->e1 = e1->e1->typ(tbl); ! 1851: if (tt->base==COBJ) { ! 1852: Pexpr x = try_to_coerce(tt,e1->e1,"type conversion",tbl); ! 1853: if (x) return x; ! 1854: } ! 1855: ! 1856: Pname acn = e1->e1->tp->is_cl_obj(); ! 1857: //error('d',"acn %n %d",acn,cl->has_itor()); ! 1858: if (acn && cl->has_itor()==0) { ! 1859: Pclass acl = Pclass(acn->tp); ! 1860: int hb = acl->has_base(cl); ! 1861: ! 1862: if (acl==cl || hb) { ! 1863: vcllist->clear(); ! 1864: vcllist=0; ! 1865: if (1<is_unique_base(acl,cl->string,0)) error("ambiguous assignment to base %t",cl); ! 1866: Pexpr ee = e1->e1; ! 1867: if (ee->base == ELIST) ee = ee->e1; // ??? ! 1868: if (hb) { // ee => *(tp2*)&ee ! 1869: // remember = may be overloaded ! 1870: //error('d',"hb %k %t %d",ee->base,ee->tp,ee->lval(0)); ! 1871: ignore_const++; ! 1872: if (ee->lval(0)==0) { ! 1873: Pname tmp = make_tmp('T',ee->tp,tbl); ! 1874: ee = init_tmp(tmp,ee,tbl); ! 1875: ee = new expr(G_CM,ee,tmp->address()); ! 1876: } ! 1877: else ! 1878: ee = ee->address(); ! 1879: ignore_const--; ! 1880: ee = new texpr(CAST,new ptr(PTR,tp2),ee); //new cast(new ptr(PTR,tp2),ee); ! 1881: ee = ee->contents(); ! 1882: ee->typ(tbl); ! 1883: } ! 1884: ! 1885: if (e2) { // x(x_obj) => e2=x_obj ! 1886: base = ASSIGN; ! 1887: e1 = e2; ! 1888: e2 = ee; ! 1889: tp = tp2; ! 1890: return this; ! 1891: } ! 1892: return ee; // strip ELIST: x(x_obj) => x_obj ! 1893: } ! 1894: } ! 1895: } ! 1896: ! 1897: ! 1898: /* x(a) => obj.ctor(a); where e1==obj */ ! 1899: Pname ctor = cl->has_ctor(); ! 1900: if (ctor == 0) { ! 1901: error("cannot make a%t",cl); ! 1902: return dummy; ! 1903: } ! 1904: ! 1905: // error('d',"e2 %k",e2?e2->base:0); ! 1906: // error('d',"refd: %d const_ptr: %d", refd, const_ptr); ! 1907: if (e2 == 0) { // x(a) => x temp; (temp.x(a),temp) ! 1908: /* incomplete condition ! 1909: if ( refd && const_ptr == 0) { ! 1910: if ( tbl == gtbl ) { ! 1911: error("Ir forG non-constCR not an lvalue"); ! 1912: } ! 1913: else ! 1914: if (strict_opt) ! 1915: error("Ir for non-constCR not an lvalue"); ! 1916: else ! 1917: if (warning_opt) ! 1918: error('w', "Ir for non-constR not an lvalue (anachronism)"); ! 1919: } ! 1920: */ ! 1921: ! 1922: no_sti = 1; ! 1923: Pname n = make_tmp('V',tp2,tbl); ! 1924: no_sti = 0; ! 1925: n->assign(); ! 1926: if (tbl == gtbl) n->dcl_print(0); // a hack ! 1927: Pexpr c = call_ctor(tbl,n,ctor,e1,DOT); ! 1928: c = new expr(G_CM,c,n); ! 1929: c->tp = n->tp; ! 1930: //error('d',"tp1 %t",c->tp); ! 1931: return c; ! 1932: } ! 1933: else { ! 1934: Pexpr c = call_ctor(tbl,e2,ctor,e1,DOT); ! 1935: c = new expr(DEREF,c,0); // deref value returned by constructor ! 1936: c->tp = c->e1->tp; ! 1937: //error('d',"tp2 %t",c->tp); ! 1938: return c; ! 1939: } ! 1940: } ! 1941: ! 1942: Pname ! 1943: gen::exactMatch(Pexpr arg, int constObj) ! 1944: /* ! 1945: look through this gen for an exact match with arg ! 1946: if found, return it; ! 1947: if ambiguous, issue error and return dummy function ! 1948: if not found, return 0; ! 1949: */ ! 1950: { ! 1951: register Plist gl; ! 1952: register int ok; ! 1953: Block(Pname) funVec; ! 1954: Pname fn = fct_list->f; ! 1955: ! 1956: register int numEx = 0; ! 1957: for (gl=fct_list; gl; gl=gl->l) { ! 1958: register Pname nn = gl->f; ! 1959: Pfct f = nn->fct_type(); ! 1960: register Pname n = f->argtype; ! 1961: if(constObj && nn->n_oper!=CTOR && !f->f_const && !f->f_static) ! 1962: continue; ! 1963: ok = 0; ! 1964: if (!arg) ok = 1; ! 1965: else { ! 1966: for(Pexpr e=arg; e; e=e->e2, n=n->n_list) { ! 1967: if (!n && f->nargs_known!=ELLIPSIS) break; ! 1968: Pexpr a = e->e1; ! 1969: Ptype at = a->tp; ! 1970: if(at->base == ANY) break; ! 1971: if (at->base == ZTYPE) at = int_type; ! 1972: if (!exact1(n,at)) break; ! 1973: if (!e->e2) ok = 1; ! 1974: } ! 1975: } ! 1976: if(!ok || n && !n->n_initializer) continue; ! 1977: ! 1978: funVec.reserve(numEx+1); ! 1979: funVec[numEx++] = nn; ! 1980: } ! 1981: ! 1982: if (!numEx) return 0; ! 1983: if (numEx==1) return funVec[0]; ! 1984: ! 1985: // see if ``const'' break ties ! 1986: Bits bestOnes = ~(Bits(0,numEx)); ! 1987: return breakTie(funVec,bestOnes,arg,constObj); ! 1988: } ! 1989: ! 1990: Pname ! 1991: gen::oneArgMatch(Pexpr aarg, int constObj) ! 1992: /* ! 1993: for a call with one argument: ! 1994: look through this gen for the best match for arg ! 1995: if found, return it; ! 1996: if ambiguous, issue error and return dummy function ! 1997: if not found, return 0; ! 1998: */ ! 1999: { ! 2000: register Plist gl; ! 2001: int numFunc = 0; ! 2002: Block(Pname) ArgVec; ! 2003: Block(Pname) funVec; ! 2004: Pname fn = fct_list->f; ! 2005: ! 2006: for (gl=fct_list; gl; gl=gl->l) { ! 2007: Pname nn = gl->f; ! 2008: Pfct ft = nn->fct_type(); ! 2009: Pname nnargs = ft->argtype; ! 2010: ! 2011: // if(template function) continue; ! 2012: if(constObj && fn->n_oper!=CTOR && ! 2013: !ft->f_const && !ft->f_static) ! 2014: continue; ! 2015: if (!nnargs && ft->nargs_known != ELLIPSIS) ! 2016: continue; ! 2017: if (nnargs && nnargs->n_list && !nnargs->n_list->n_initializer) ! 2018: continue; ! 2019: ArgVec.reserve(numFunc+1); ! 2020: funVec.reserve(numFunc+1); ! 2021: ArgVec[numFunc] = nnargs ? nnargs : (Pname)ELLIPSIS; ! 2022: funVec[numFunc++] = nn; ! 2023: } ! 2024: if(!numFunc) return 0; ! 2025: ! 2026: Bits bestOnes = bestMatch(ArgVec, numFunc, aarg->e1->tp); ! 2027: ! 2028: int numFuncs = bestOnes.count(); ! 2029: if(!numFuncs) return 0; ! 2030: if(numFuncs == 1) ! 2031: return funVec[bestOnes.signif() - 1]; ! 2032: ! 2033: return breakTie(funVec,bestOnes,aarg,constObj); ! 2034: } ! 2035: ! 2036: Pname ! 2037: gen::multArgMatch(Pexpr arg, int constObj) ! 2038: /* ! 2039: for a call with multiple arguments: ! 2040: look through this gen for the best match for arg ! 2041: if found, return it; ! 2042: if ambiguous, issue error and return dummy function ! 2043: if not found, return 0; ! 2044: */ ! 2045: { ! 2046: int numargs = 1; ! 2047: Pexpr tmp = arg; ! 2048: while((tmp=tmp->e2)) numargs++; ! 2049: Block(Block_Pname) intFun(numargs); ! 2050: Pname fn = fct_list->f; ! 2051: ! 2052: miFlag = 0; ! 2053: register int numFunc = 0; ! 2054: Block(Pname) funVec; ! 2055: ! 2056: for (Plist gl=fct_list; gl; gl=gl->l) { ! 2057: register Pname nn = gl->f; ! 2058: ! 2059: // first weed out unmatchable functions ! 2060: if (!matchable(nn,arg,constObj)) continue; ! 2061: ! 2062: // store types in ``matrix'' for bestMatching ! 2063: register int ai = 0; ! 2064: Pfct tf = nn->fct_type(); ! 2065: ! 2066: funVec.reserve(numFunc+1); ! 2067: funVec[numFunc] = nn; ! 2068: for (Pname x=tf->argtype; x&&ai<numargs; x=x->n_list) { ! 2069: intFun[ai].reserve(numFunc+1); ! 2070: intFun[ai][numFunc] = x; ! 2071: ai++; ! 2072: } ! 2073: ! 2074: // extend ellipsis arguments ! 2075: if(tf->nargs_known == ELLIPSIS) { ! 2076: while(ai < numargs) { ! 2077: intFun[ai].reserve(numFunc+1); ! 2078: intFun[ai++][numFunc] = (Pname)ELLIPSIS; ! 2079: } ! 2080: } ! 2081: numFunc++; ! 2082: } ! 2083: ! 2084: // no matchable functions ! 2085: if(numFunc == 0) return 0; ! 2086: ! 2087: // finished: only one matchable function ! 2088: if(numFunc == 1) return funVec[0]; ! 2089: ! 2090: // more matchable functions: need intersect rule ! 2091: if(numFunc > 1) { ! 2092: ! 2093: Bits bestFuncs = intersectRule(intFun,numFunc,arg); ! 2094: ! 2095: Pname best = 0; ! 2096: register int sigbit = bestFuncs.signif() - 1; ! 2097: ! 2098: switch(bestFuncs.count()) { ! 2099: case 0: // null intersection ! 2100: fmError(1,funVec,arg); ! 2101: best = funVec[0]; ! 2102: break; ! 2103: ! 2104: default: //multiple elements in intersection ! 2105: best = breakTie(funVec,bestFuncs,arg,constObj); ! 2106: sigbit = bestFuncs.signif() - 1; ! 2107: ! 2108: case 1: // one element in intersection ! 2109: // before or after breakTie ! 2110: if (miFlag==1 && numFunc > 2) { ! 2111: // suspect: need simple rule ! 2112: for(int K = 0; K < numFunc; K++) { ! 2113: if(K == sigbit) continue; ! 2114: int gotit = 0; ! 2115: Pexpr targ = arg; ! 2116: for(int I=0;I<numargs;I++) { ! 2117: if(bestOfPair(intFun[I][sigbit], ! 2118: intFun[I][K],targ->e1->tp)) { ! 2119: gotit = 1; ! 2120: break; ! 2121: } ! 2122: targ = targ->e2; ! 2123: } ! 2124: if(!gotit) { ! 2125: if(!best) { ! 2126: fmError(1,funVec,arg); ! 2127: break; ! 2128: } ! 2129: Bits temp = bestFuncs; ! 2130: bestFuncs.set(K); ! 2131: if(breakTie( ! 2132: funVec, ! 2133: temp, ! 2134: arg, ! 2135: constObj)!=funVec[sigbit]) { ! 2136: fmError(1,funVec,arg); ! 2137: break; ! 2138: } ! 2139: } ! 2140: } ! 2141: } ! 2142: best = funVec[sigbit]; ! 2143: } ! 2144: return best; ! 2145: } ! 2146: } ! 2147: ! 2148: Bits bestMatch(const Block(Pname)& AV, int nav, Ptype at) ! 2149: /* ! 2150: find the indices of the elements of AV which best match at. ! 2151: return a Bits with bits set which correspond to these indices ! 2152: */ ! 2153: { ! 2154: Bits zeroBits(0,nav); ! 2155: ! 2156: Bits result = zeroBits; ! 2157: Block(int) rate(nav); ! 2158: Block(Pname) udcBlock(nav); ! 2159: extern int miFlag; ! 2160: ! 2161: int i = -1; ! 2162: while(++i < nav) { ! 2163: ! 2164: Pname aa = AV[i]; ! 2165: ! 2166: if(aa == 0) continue; ! 2167: ! 2168: if(aa == (Pname)ELLIPSIS) { ! 2169: rate[i] = ELLIP; ! 2170: continue; ! 2171: } ! 2172: Ptype t1 = aa->tp; ! 2173: ! 2174: if (t1==at || exact1(aa,at)) { ! 2175: rate[i] = EXACT; ! 2176: continue; ! 2177: } ! 2178: if (exact2(aa,at)) { ! 2179: rate[i] = PROM; ! 2180: continue; ! 2181: } ! 2182: if (exact3(aa,at)) { ! 2183: rate[i] = STD; ! 2184: continue; ! 2185: } ! 2186: ! 2187: if (can_coerce(t1,at)) { ! 2188: udcBlock[i] = Ncoerce; ! 2189: rate[i] = UDC; ! 2190: continue; ! 2191: } ! 2192: ! 2193: rate[i] = NONE; ! 2194: } ! 2195: ! 2196: int max = NONE; ! 2197: for(i=0;i<nav;i++) { ! 2198: if( rate[i] > max ) { ! 2199: max = rate[i]; ! 2200: result = zeroBits; ! 2201: } ! 2202: if( rate[i] && rate[i] == max ) { ! 2203: result.set(i); ! 2204: } ! 2205: } ! 2206: ! 2207: if (result.count() <= 1) return result; ! 2208: ! 2209: // break ties for STD's involving inheritance ! 2210: if (max == STD ) { ! 2211: if(at->is_ptr_or_ref()) at = Pptr(at)->typ; ! 2212: if (!at->is_cl_obj()) return result; ! 2213: ! 2214: Bits tempBits = result; ! 2215: tempBits.reset(tempBits.signif() - 1); ! 2216: ! 2217: // nice little algo to find ``real'' best matches ! 2218: // taking derivation and MI into account ! 2219: while(tempBits.count()) { ! 2220: int tempPtr = tempBits.signif() - 1; ! 2221: Ptype t1 = AV[tempPtr]->tp; ! 2222: for(int k = nav - 1; k > tempPtr; k--) { ! 2223: if(!result[k]) continue; ! 2224: Ptype t2 = AV[k]->tp; ! 2225: int r = pr_dominate(t1,t2); ! 2226: if (r==1 || ! 2227: t2->base==PTR && Pptr(t2)->typ->base==VOID) { ! 2228: result.reset(k); ! 2229: } ! 2230: if (r==2 || ! 2231: t1->base==PTR && Pptr(t1)->typ->base==VOID) { ! 2232: result.reset(tempPtr); ! 2233: break; ! 2234: } ! 2235: if(r==0 && miFlag==0) miFlag = 1; ! 2236: } ! 2237: tempBits.reset(tempPtr); ! 2238: } ! 2239: } ! 2240: ! 2241: // find UDC sequences which are prefix's of others ! 2242: if (max == UDC ) { ! 2243: Bits tempBits = result; ! 2244: int sigbit = tempBits.signif() - 1; ! 2245: tempBits.reset(sigbit); ! 2246: ! 2247: while(tempBits.count()) { ! 2248: int tempPtr = tempBits.signif() - 1; ! 2249: Pname tname = AV[tempPtr]; ! 2250: for(int k = nav - 1; k > tempPtr; k--) { ! 2251: if(!result[k] || !udcBlock[k]) continue; ! 2252: Ptype tt = udcBlock[k]->fct_type()->returns; ! 2253: Pname r = udcBlock[tempPtr]==udcBlock[k] ? ! 2254: bestOfPair(tname,AV[k],tt) : 0; ! 2255: if (r==tname) ! 2256: result.reset(k); ! 2257: if (r==AV[k]) { ! 2258: result.reset(tempPtr); ! 2259: break; ! 2260: } ! 2261: } ! 2262: tempBits.reset(tempPtr); ! 2263: } ! 2264: } ! 2265: ! 2266: return result; ! 2267: } ! 2268: ! 2269: Pname bestOfPair(Pname a1, Pname a2, Ptype at) ! 2270: /* ! 2271: return the bestMatch of a pair of names to at if ! 2272: one exists. ! 2273: otherwise, return 0; ! 2274: */ ! 2275: { ! 2276: if(a1->tp == a2->tp) return 0; ! 2277: ! 2278: Block(Pname) tryBlock(3); ! 2279: tryBlock[0] = a1; ! 2280: tryBlock[1] = a2; ! 2281: Bits bestBits = bestMatch(tryBlock,2,at); ! 2282: if (bestBits.count()==1) { ! 2283: return tryBlock[bestBits.signif() - 1]; ! 2284: } ! 2285: return 0; ! 2286: } ! 2287: ! 2288: Bits intersectRule(const Block(Block_Pname)& intFun, int numFunc, Pexpr arg) ! 2289: /* ! 2290: intersect rule ! 2291: */ ! 2292: { ! 2293: Bits zeroBits(0,numFunc); ! 2294: Bits result = ~zeroBits; ! 2295: ! 2296: int ai = 0; ! 2297: for(Pexpr aargu = arg; aargu; aargu = aargu->e2) { ! 2298: Ptype at = aargu->e1->tp; ! 2299: Bits tryit = bestMatch(intFun[ai++],numFunc,at); ! 2300: if(tryit.count()==1) miFlag = -1; ! 2301: result &= tryit; ! 2302: if(!result.count()) { return zeroBits; } ! 2303: } ! 2304: return result; ! 2305: } ! 2306: ! 2307: Pname breakTie(const Block(Pname)& FV,Bits& bestOnes,Pexpr arg,int cO) ! 2308: /* ! 2309: all functions in Block are equal after the intersect rule ! 2310: use a mini-intersect rule on the array to see if one dominates ! 2311: all others when trivial conversions involving const are ! 2312: considered. ! 2313: ! 2314: if so, return it; ! 2315: if not, issue ambiguity error and return any function ! 2316: */ ! 2317: { ! 2318: register int numFunc = bestOnes.size(); ! 2319: Bits zeroBits(0,numFunc); ! 2320: Bits result = ~zeroBits; ! 2321: ! 2322: Block(Pname) rfunc(numFunc); ! 2323: ! 2324: int i = 0, ni=0; ! 2325: while(FV[i]) { ! 2326: if(bestOnes[i]) rfunc[i]=FV[i]->fct_type()->argtype; ! 2327: i++; ! 2328: } ! 2329: ! 2330: int stat = FV[bestOnes.signif()-1]->fct_type()->f_static; ! 2331: ! 2332: // see if ``const'' breaks tie ! 2333: for(Pexpr aargu = arg; aargu; aargu = aargu->e2) { ! 2334: Ptype at = aargu->e1->tp; ! 2335: Bits temp = zeroBits; ! 2336: for(int k = 0; k < numFunc; k++) { ! 2337: if(bestOnes[k]) { ! 2338: if(stat != FV[k]->fct_type()->f_static) { ! 2339: result = zeroBits; ! 2340: break; ! 2341: } ! 2342: if(rfunc[k]) { ! 2343: Ptype t1 = rfunc[k]->tp; ! 2344: Pptr r1 = t1->is_ref(); ! 2345: ! 2346: if(at->check(t1,0)==0 && const_problem==0) ! 2347: temp.set(k); ! 2348: else if(r1 && r1->typ->check(at,0)==0 ! 2349: && const_problem==0) ! 2350: temp.set(k); ! 2351: rfunc[k] = rfunc[k]->n_list; ! 2352: } ! 2353: } ! 2354: } ! 2355: if(temp.count()) result &= temp; ! 2356: ! 2357: if(!result.count()) break; ! 2358: } ! 2359: ! 2360: Pfct pf = FV[0]->fct_type(); ! 2361: if(result.count()>=1 && pf->memof) { // && FV[0]->n_oper != CTOR) { ! 2362: Bits temp = zeroBits; ! 2363: for(int k = 0; k < numFunc; k++) { ! 2364: if(bestOnes[k]) { ! 2365: if(cO == FV[k]->fct_type()->f_const) temp.set(k); ! 2366: } ! 2367: } ! 2368: if(temp.count()) result &= temp; ! 2369: } ! 2370: ! 2371: if(result.count()==0 || result.count()>=2) { ! 2372: fmError(1,FV,arg); ! 2373: miFlag = 0; ! 2374: } ! 2375: else bestOnes = result; ! 2376: ! 2377: return FV[bestOnes.signif() - 1]; ! 2378: } ! 2379: ! 2380: void fmError(int errorKind, const Block(Pname)& FV, Pexpr arg) ! 2381: { ! 2382: ! 2383: Pname fn = FV[0]->tp->base==OVERLOAD ? ! 2384: Pgen(FV[0]->tp)->fct_list->f : FV[0]; ! 2385: ! 2386: switch (errorKind) { ! 2387: case 0: ! 2388: error('e',"illegal call: "); ! 2389: break; ! 2390: case 1: ! 2391: error('e',"ambiguous call: "); ! 2392: break; ! 2393: } ! 2394: ! 2395: // call ! 2396: if(fn->n_oper && fn->n_oper!=CTOR) ! 2397: error('c',"operator%s(",keys[fn->n_oper]); ! 2398: else error('c',"%s(",fn->string); ! 2399: if(arg) { ! 2400: Pexpr tmp = arg; ! 2401: error('c',"%t",tmp->e1->tp); ! 2402: while((tmp=tmp->e2)) { ! 2403: error('c',",%t",tmp->e1->tp); ! 2404: } ! 2405: } ! 2406: error('c',")\n"); ! 2407: ! 2408: // possible functions ! 2409: error('C',"choice of%ns:\n",fn); ! 2410: ! 2411: if(FV[0]->tp->base == OVERLOAD) { ! 2412: for(Plist gl = Pgen(FV[0]->tp)->fct_list;gl;gl=gl->l) { ! 2413: error('C'," %t;\n",gl->f->tp); ! 2414: } ! 2415: return; ! 2416: } ! 2417: ! 2418: int numFunc = FV.size(); ! 2419: for(int i=0; i<numFunc; i++) { ! 2420: if(FV[i]) error('C'," %t;\n",FV[i]->tp); ! 2421: } ! 2422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.