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