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