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