|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/dcl3.c 1.6.5.29" */ ! 2: /************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: dcl3.c: ! 11: Routines used by ::dcl fucntions: fct::dcl() etc. ! 12: ! 13: *****************************************************************************/ ! 14: ! 15: #include "cfront.h" ! 16: #include "size.h" ! 17: #include "template.h" ! 18: ! 19: extern loc no_where; ! 20: static void vbase_pointers(Pname fn, Pclass cl) ! 21: /* ! 22: insert argument for virtual base pointers (if any) ! 23: after f_this and before f_argtype ! 24: */ ! 25: { ! 26: //error('d',"vbase_pointers(%n,%t) %d %k",fn,cl,fn->tp,fn->n_oper); ! 27: Pfct f = Pfct(fn->tp); ! 28: if (fn->n_oper == CTOR) { ! 29: Pname d = 0; ! 30: for (Pbcl b = cl->baselist; b; b=b->next) { ! 31: if (b->base != VIRTUAL) continue; ! 32: Pname a = new name(b->bclass->string); ! 33: a->tp = b->bclass->this_type; ! 34: a->n_list = d; ! 35: a->n_table = f->body ? f->body->memtbl : 0; ! 36: a->where = no_where; ! 37: d = a; ! 38: } ! 39: ! 40: if (d) { ! 41: for (Pname dd =d;;) { ! 42: if (d->n_list == 0) { ! 43: d->n_list = f->f_args->n_list; ! 44: break; ! 45: } ! 46: d = d->n_list; ! 47: } ! 48: f->f_args->n_list = dd; ! 49: } ! 50: } ! 51: if (fn->n_oper == DTOR) { // add __free argument ! 52: //error('d',"add __free to %n",fn); ! 53: Pname fa = new name; ! 54: fa->tp = int_type; ! 55: fa->n_scope = ARG; ! 56: fa->where = no_where; ! 57: ! 58: Pname a = f->f_args; ! 59: if (a == 0) ! 60: f->f_args = fa; ! 61: else { ! 62: for(;;a = a->n_list) { ! 63: // error('d',"a %d %t",a,a->tp); ! 64: if (a->n_list == 0) { ! 65: a->n_list = fa; ! 66: break; ! 67: } ! 68: } ! 69: } ! 70: } ! 71: } ! 72: ! 73: void make_res(Pfct f) ! 74: /* ! 75: returns X where X(X&) has been declared ! 76: add "_result" argument of type X* ! 77: */ ! 78: { ! 79: Pname cl = f->returns->is_cl_obj(); ! 80: if (cl==0 || Pclass(cl->tp)->has_itor()==0) return; ! 81: ! 82: Pname rv = new name("_result"); ! 83: rv->tp = f->returns->addrof(); ! 84: rv->n_scope = FCT; // not a ``real'' argument ! 85: rv->n_used = 1; ! 86: rv->n_list = f->argtype; ! 87: if (f->f_this) ! 88: f->f_this->n_list = rv; ! 89: else ! 90: f->f_args = rv; ! 91: f->f_result = rv; ! 92: f->s_returns = void_type; ! 93: } ! 94: ! 95: void name::check_oper(Pname cn) ! 96: /* ! 97: check declarations of operators, ctors, dtors ! 98: */ ! 99: { ! 100: switch (n_oper) { ! 101: case CALL: ! 102: case DEREF: ! 103: case REF: ! 104: if (cn == 0) error("operator%s must be aM",keys[n_oper]); ! 105: break; ! 106: // case ASPLUS: ! 107: // case ASMINUS: ! 108: // case ASMUL: ! 109: // case ASDIV: ! 110: // case ASMOD: ! 111: // case ASAND: ! 112: // case ASOR: ! 113: // case ASER: ! 114: // case ASLS: ! 115: // case ASRS: ! 116: case ASSIGN: ! 117: if (cn == 0) error('w',"operator%k() must be aM (thisD will soon cease to compile)",n_oper); ! 118: break; ! 119: case 0: ! 120: case TNAME: /* may be a constructor */ ! 121: if (cn && ! 122: ((strcmp(cn->string,string)==0) || ! 123: ((Pclass(cn->tp)->class_base == instantiated_template_class)&& ! 124: (strcmp(string, ! 125: Ptclass(cn->tp)->unparametrized_tname()->string) ! 126: == 0)))) ! 127: ! 128: { ! 129: if (tp->base == FCT) { ! 130: Pfct f = Pfct(tp); ! 131: if (f->returns!=defa_type) ! 132: error("%s::%s()W returnT",string,string); ! 133: f->returns = void_type; ! 134: string = "__ct"; ! 135: n_oper = CTOR; ! 136: } ! 137: else ! 138: error('s',"struct%nM%n",cn,cn); ! 139: } ! 140: else ! 141: n_oper = 0; ! 142: break; ! 143: case DTOR: /* must be a destructor */ ! 144: //error('d',"dtor %s",string); ! 145: if (cn == 0) { ! 146: n_oper = 0; ! 147: error("destructor ~%s() not inC",string); ! 148: } ! 149: else if ((strcmp(cn->string,string) == 0) || ! 150: ((Pclass(cn->tp)->class_base == ! 151: instantiated_template_class) && ! 152: (strcmp(string, ! 153: Ptclass(cn->tp)->unparametrized_tname()->string) ! 154: == 0))){ ! 155: dto: ! 156: Pfct f = (Pfct)tp; ! 157: string = "__dt"; ! 158: if (tp->base != FCT) { ! 159: error("%s::~%s notF",cn->string,cn->string); ! 160: tp = new fct(void_type,0,1); ! 161: } ! 162: else if (f->returns!=defa_type/* && f->returns!=void_type*/) ! 163: error("%s::~%s()W returnT",cn->string,cn->string); ! 164: if (f->argtype) { ! 165: error("%s::~%s()WAs",cn->string,cn->string); ! 166: f->nargs = 0; ! 167: f->nargs_known = 1; ! 168: f->argtype = 0; ! 169: } ! 170: f->returns = void_type; ! 171: } ! 172: else { ! 173: if (strcmp(string,"__dt") == 0) goto dto; ! 174: error("~%s in %s",string,cn->string); ! 175: n_oper = 0; ! 176: } ! 177: break; ! 178: case TYPE: ! 179: //error('d',"type %t",n_initializer); ! 180: if (cn == 0) { ! 181: error("operator%t() not aM",Ptype(n_initializer)); ! 182: n_oper = 0; ! 183: n_initializer = 0; ! 184: } ! 185: else { ! 186: Pfct f = Pfct(tp); ! 187: Ptype tx = Ptype(n_initializer); ! 188: n_initializer = 0; ! 189: if (f->base != FCT) error("badT for%n::operator%t()",cn,tx); ! 190: if (f->returns != defa_type) { ! 191: // if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx); ! 192: error("resultT for%n::operator%t()",cn,tx); ! 193: DEL(f->returns); ! 194: } ! 195: if (f->argtype) { ! 196: error("%n::operator%t()WAs",cn,tx); ! 197: f->argtype = 0; ! 198: } ! 199: f->returns = tx; ! 200: Pname nx = tx->is_cl_obj(); ! 201: if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx); ! 202: char buf[1024]; ! 203: char* bb = tx->signature(buf); ! 204: int l2 = bb-buf; ! 205: if (1023<l2) error('i',"N::check_oper():N buffer overflow"); ! 206: char* p = new char[l2+5]; ! 207: p[0] = '_'; ! 208: p[1] = '_'; ! 209: p[2] = 'o'; ! 210: p[3] = 'p'; ! 211: strcpy(p+4,buf); ! 212: string = p; ! 213: } ! 214: break; ! 215: } ! 216: } ! 217: ! 218: Pexpr vbase_args(Pfct a, Pname bn) ! 219: /* ! 220: constructor a calls the constructor bn for a base class ! 221: generate argument list needed for virtual base arguments ! 222: */ ! 223: { ! 224: Pfct b = Pfct(bn->tp); ! 225: //error('d',"vbase_args%n: %t %k",bn,b,b->base); ! 226: Pexpr args = 0; ! 227: Pexpr tail = 0; ! 228: if (b->base == OVERLOAD) b = Pfct(Pgen(b)->fct_list->f->tp); // doesn't matter which ! 229: for (Pname d = b->f_args->n_list; d!=b->argtype; d=d->n_list) { ! 230: for (Pname dd = a->f_args->n_list; dd; dd=dd->n_list) ! 231: // using strcmp is a trick ! 232: if (strcmp(dd->string,d->string)==0) break; ! 233: ! 234: Pexpr aa = new expr(ELIST,dd,0); ! 235: if (args == 0) ! 236: args = aa; ! 237: else ! 238: tail->e2 = aa; ! 239: tail = aa; ! 240: } ! 241: return args; ! 242: } ! 243: ! 244: void fct::init_bases(Pclass cl, Pexpr) ! 245: /* ! 246: in "cl"'s constructor "this" generate code to initialize base classes ! 247: and members using the initializers "f->f_init" ! 248: ! 249: this->f_init == list of names of classes to be initialized ! 250: COLON(b) => base class b ! 251: => constructor call in f_init->n_initializer ! 252: COLON() => unnamed base class ! 253: => constructor call in f_init->n_initializer ! 254: NAME(m) => member m ! 255: => constructor call in m->n_initializer ! 256: */ ! 257: { ! 258: Ptable ftbl = body->memtbl; ! 259: //error('d',"init_bases %t init %d",cl,f_init); ! 260: ! 261: // explicit initializers ! 262: for (Pname nx, nn=f_init; nn; delete nn,(nn=nx) ) { ! 263: Pexpr i = nn->n_initializer; ! 264: nn->n_initializer = 0; ! 265: nx = nn->n_list; ! 266: ! 267: //error('d',"init_base %s %d",nn->string,i); ! 268: if (nn->string) { ! 269: if (nn->base == TNAME) { // base class ! 270: for (Pbcl l = cl->baselist; l; l=l->next) { ! 271: Pclass bcl = l->bclass; ! 272: if ((strcmp(bcl->string,nn->string) == 0) || ! 273: ((bcl->class_base == ! 274: instantiated_template_class) && ! 275: ((strcmp( ! 276: Ptclass(bcl)->unparametrized_tname()->string, nn->string)) == 0))) ! 277: ! 278: { ! 279: if (l->init) ! 280: error("twoIrs for%t",bcl); ! 281: else ! 282: l->init = base_init(bcl,i,ftbl,l->obj_offset); ! 283: goto con; ! 284: } ! 285: } ! 286: error("unexpectedAL: noBC%n",nn); ! 287: con: ! 288: continue; ! 289: } ! 290: else { // member initializer ! 291: Pname m = cl->memtbl->look(nn->string,0); ! 292: if (m && m->n_table==cl->memtbl) ! 293: m->n_initializer = mem_init(m,i,ftbl); ! 294: else ! 295: error("%n not inC%n",m,nn); ! 296: } ! 297: } ! 298: else { // unnamed base class ! 299: Pbcl l = cl->baselist; ! 300: if (l == 0) { ! 301: error("unexpectedAL: noBC called"); ! 302: continue; ! 303: } ! 304: ! 305: if (l->next) { ! 306: error("unnamedBCIr: multipleBCs"); ! 307: continue; ! 308: } ! 309: ! 310: if (l->init) ! 311: error("twoIrs for%t",l->bclass); ! 312: else { ! 313: if (strict_opt) error("anachronism:N ofBC %t missing",l->bclass); ! 314: l->init = base_init(l->bclass,i,ftbl,l->obj_offset); ! 315: } ! 316: } ! 317: } // for ! 318: ! 319: for (Pbcl l = cl->baselist; l; l=l->next) { ! 320: // default initialization of base classes ! 321: Pname ctor; ! 322: Pclass bcl = l->bclass; ! 323: if (l->init==0 && (ctor=bcl->has_ctor())) ! 324: l->init = base_init(bcl,0,ftbl,l->obj_offset); ! 325: } ! 326: } ! 327: ! 328: int inline_restr; /* report use of constructs that the inline expanded ! 329: cannot handle here ! 330: */ ! 331: ! 332: void fct::dcl(Pname n) ! 333: { ! 334: int nmem = TBLSIZE; ! 335: Pname a; ! 336: Pname ll; ! 337: Ptable ftbl; ! 338: ! 339: Pptr cct = 0; ! 340: int const_old = const_save; ! 341: ! 342: int bit_old = bit_offset; ! 343: int byte_old = byte_offset; ! 344: int max_old = max_align; ! 345: ! 346: if (base != FCT) error('i',"F::dcl(%d)",base); ! 347: if (body == 0) error('i',"F::dcl(body=%d)",body); ! 348: if (n==0 || n->base!=NAME) error('i',"F::dcl(N=%d %d)",n,(n)?n->base:0); ! 349: //error('d',"fct::dcl(%n) %k %d %t",n,n->n_scope,body->own_tbl,this); ! 350: if (body->own_tbl) return; // done already ! 351: ! 352: // if (f_inline==0 /*|| debug_opt*/) n->n_dcl_printed = 1; // beware of recursive calls, no decl needed ! 353: // if (f_inline && debug_opt) n->n_dcl_printed = 2; ! 354: if (body->memtbl == 0) body->memtbl = new table(nmem+3,gtbl,0); ! 355: body->own_tbl = 1; ! 356: ftbl = body->memtbl; ! 357: ftbl->real_block = body; ! 358: ! 359: max_align = 0;//AL_FRAME; ! 360: bit_offset = 0; ! 361: ! 362: cc->stack(); ! 363: cc->nof = n; ! 364: cc->ftbl = ftbl; ! 365: ! 366: switch (n->n_scope) { ! 367: case 0: ! 368: case PUBLIC: ! 369: { cc->not = n->n_table->t_name; ! 370: cc->cot = Pclass(cc->not->tp); ! 371: cc->tot = cc->cot->this_type; ! 372: // if (f_this==0 || cc->tot==0) error('i',"F::dcl(%n): f_this=%d cc->tot=%d",n,f_this,cc->tot); ! 373: if (f_this) f_this->n_table = ftbl; // fake for inline printout ! 374: cc->c_this = f_this; ! 375: ! 376: ! 377: Pclass cl = Pclass(cc->not->tp); ! 378: ! 379: if (cl->c_body!=3 ! 380: || n->n_initializer ! 381: || n->n_sto==STATIC ! 382: || f_inline ! 383: || f_imeasure ! 384: || f_virtual==0) ! 385: ; ! 386: else { // could be the function where we need to ! 387: // output the vtbl ! 388: int i; ! 389: for (Pname nn=cl->memtbl->get_mem(i=1); nn; nn=cl->memtbl->get_mem(++i) ) { ! 390: Ptype t = nn->tp; ! 391: if (t) ! 392: switch (t->base) { ! 393: case FCT: ! 394: if (nn == n) goto prnt; ! 395: if (nn->n_initializer ! 396: || nn->n_sto==STATIC ! 397: || Pfct(nn->tp)->f_inline ! 398: || Pfct(nn->tp)->f_imeasure ! 399: || Pfct(nn->tp)->f_virtual==0) break; ! 400: goto zaq; ! 401: ! 402: case OVERLOAD: ! 403: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) { ! 404: Pname nn = gl->f; ! 405: if (nn == n) goto prnt; ! 406: if (nn->n_initializer ! 407: || nn->n_sto==STATIC ! 408: || Pfct(nn->tp)->f_inline ! 409: || Pfct(nn->tp)->f_imeasure ! 410: || Pfct(nn->tp)->f_virtual==0) continue; ! 411: goto zaq; ! 412: } ! 413: } ! 414: } ! 415: } ! 416: goto zaq; ! 417: prnt: ! 418: cl->print_all_vtbls(cl); ! 419: goto zaq; ! 420: } ! 421: } ! 422: } ! 423: zaq: ! 424: // protect against: class x; x f(); class x { x(x&); .... ! 425: if (f_result == 0) make_res(this); ! 426: if (f_result) f_result->n_table = ftbl; // fake for inline printout ! 427: ! 428: returns->tsizeof(); // make sure size is known ! 429: ! 430: Pname ax; ! 431: for (a=argtype, ll=0; a; a=ax) { ! 432: ax = a->n_list; ! 433: Pname nn = a->dcl(ftbl,ARG); ! 434: Pname cn = nn->tp->is_cl_obj(); ! 435: if (cn == 0) cn = cl_obj_vec; ! 436: if (cn) (void)cn->tp->tsizeof(); // make sure it is printed ! 437: nn->n_assigned_to = nn->n_used = nn->n_addr_taken = 0; ! 438: nn->n_list = 0; ! 439: ! 440: switch (nn->tp->base) { ! 441: case CLASS: ! 442: case ENUM: /* unlink types declared in arg list */ ! 443: nn->dcl_print(0); ! 444: break; ! 445: default: ! 446: if (ll) ! 447: ll->n_list = nn; ! 448: else ! 449: f_args = argtype = nn; ! 450: ll = nn; ! 451: } ! 452: delete a; ! 453: } ! 454: ! 455: if (f_result) { // link in f_result ! 456: f_args = f_result; ! 457: f_result->n_list = argtype; ! 458: } ! 459: ! 460: if (f_this) { // link in f_this ! 461: f_args = f_this; ! 462: f_this->n_list = f_result ? f_result : argtype; ! 463: } ! 464: ! 465: if (n->n_oper==CTOR || n->n_oper==DTOR) vbase_pointers(n,cc->cot); ! 466: ! 467: if (n->n_oper == CTOR) { ! 468: const_save = 1; ! 469: init_bases(cc->cot,f_init); ! 470: } ! 471: else if (f_init) ! 472: error(0,"unexpectedAL: not aK"); ! 473: ! 474: PERM(returns); ! 475: const_save = f_inline&&debug_opt==0; ! 476: inline_restr = 0; ! 477: body->dcl(ftbl); ! 478: ! 479: defined |= DEFINED; ! 480: if (f_inline && inline_restr && returns->base!=VOID) { ! 481: f_inline = 0; ! 482: char* s = (inline_restr & 32) ? "continue" ! 483: : (inline_restr & 16) ? "break" ! 484: : (inline_restr & 8) ? "loop" ! 485: : (inline_restr & 4) ? "switch" ! 486: : (inline_restr & 2) ? "goto" ! 487: : (inline_restr & 1) ? "label" ! 488: : "" ; ! 489: error('w', "\"inline\" ignored, %n contains %s",n,s); ! 490: // if (cc->cot) ! 491: n->simpl(); //BS6 ! 492: n->dcl_print(0); ! 493: } ! 494: const_save = const_old; ! 495: ! 496: if (f_inline && debug_opt==0) isf_list = new name_list(n,isf_list); ! 497: ! 498: bit_offset = bit_old; ! 499: byte_offset = byte_old; ! 500: max_align = max_old; ! 501: cc->unstack(); ! 502: //error('d',"fct-> returns %t",returns); ! 503: } ! 504: ! 505: Pexpr fct::base_init(Pclass bcl, Pexpr i, Ptable ftbl, int offset) ! 506: /* ! 507: have base class bcl and expr list i ! 508: return "( *(base*)this ) . ctor( i )" ! 509: ctor call generated in expr.typ() ! 510: */ ! 511: { ! 512: Ptype ty = bcl->this_type; ! 513: Pexpr th = rptr(ty,f_this,offset); // base* ! 514: Pname ctor = bcl->has_ctor(); ! 515: ! 516: //error('d',"fct::B_init(C %t, i %d, %d) ctor %n",bcl,i,i?i->tp:0,ctor); ! 517: ! 518: Pexpr ii = (i && i->base==ELIST)?i->e1:i; ! 519: ! 520: if (ii ! 521: && ii->base==DEREF ! 522: && ii->e1->base==CAST ! 523: && th->base==CAST) th->i2 = ii->e1->i2; ! 524: ! 525: if (ctor == 0) { ! 526: if (i && i->base!=ELIST) i = new expr(ELIST,i,0); ! 527: ! 528: Pexpr v = new texpr(VALUE,bcl,i); // ?.base(i) ! 529: v->e2 = new expr(DEREF,th,0); // (*(base*)this).base(i) ! 530: v = v->typ(ftbl); // *base(&*(base*)this,i) ! 531: //error('d',"v %k",v->base); ! 532: switch (v->base) { ! 533: case DEREF: ! 534: return v->e1; // base(&*(base*)this,i) ! 535: case ASSIGN: // degenerate base(base&): *(base*)this=i ! 536: th = new texpr(CAST,ty,f_this); ! 537: v = new expr(CM,v,th); // (*(base*)this=i,(base*)this); ! 538: return v->typ(ftbl); ! 539: default: ! 540: return 0; ! 541: } ! 542: } ! 543: ! 544: ! 545: Pname icn; ! 546: if (i) { ! 547: ii = ii->typ(ftbl); ! 548: if (bcl->has_itor()==0 ! 549: && (icn=ii->tp->is_cl_obj()) ! 550: && (Pclass(icn->tp)==bcl || Pclass(icn->tp)->has_base(bcl))) { ! 551: // degenerate base(base&): *(base*)this=i ! 552: // memberwise copy ! 553: //error('d',"copy %t",ty); ! 554: // th = new cast(ty,f_this); ! 555: // th = th->contents(); ! 556: th = new texpr(CAST,ty,f_this); ! 557: th = th->contents(); ! 558: th = th->typ(ftbl); ! 559: if (Pclass(icn->tp)!=bcl) { // cast needed ! 560: Pptr r = new ptr(RPTR,Pptr(ty)->typ); ! 561: ii = new texpr(CAST,r,ii); ! 562: ii = ii->typ(ftbl); ! 563: } ! 564: ii = new expr(ASSIGN,th,ii); ! 565: ii->tp = th->tp; ! 566: // simulate `return this': ! 567: // *(base*)this=i,(base*)this ! 568: ii = new expr(CM,ii,new cast(ty,f_this)); ! 569: ii->tp = th->tp; ! 570: return ii; ! 571: // return ii->typ(ftbl); // don't find cl::operator=() ! 572: } ! 573: if (i->base == ELIST) i->e1 = ii; ! 574: } ! 575: //Pexpr x = call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor)); ! 576: //error('d',"call %n %t -> %d %k",ctor,ctor->tp,x,x->base); ! 577: // return x; ! 578: return call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor)); ! 579: } ! 580: ! 581: ! 582: Pexpr fct::mem_init(Pname mn, Pexpr i, Ptable ftbl) ! 583: /* ! 584: return "member_ctor( m, i )" ! 585: */ ! 586: { ! 587: // a new entry for B::B_pub, in general, has no tp and no ! 588: // real info: all the tp-> only work on our systems because ! 589: // 0 pointer dereference isn't system memory. it core dumps ! 590: // in set_const since no test is made on this == 0. ! 591: //error('d',"mem_init %n",mn); ! 592: ! 593: // if (mn->n_stclass == STATIC) error('s',"MIr for static%n",mn); ! 594: switch (mn->n_stclass) { ! 595: case STATIC: ! 596: error("MIr for static%n",mn); ! 597: break; ! 598: case ENUM: ! 599: error("MIr for enumeration constant%n", mn); ! 600: break; ! 601: } ! 602: ! 603: Pname member = (mn->base==PUBLIC && mn->n_qualifier) ? mn->n_qualifier : mn; ! 604: ! 605: if (i) i = i->typ(ftbl); ! 606: Pname cn = member->tp->is_cl_obj(); // first find the class name ! 607: ! 608: // if (member->n_stclass == STATIC) error('s',"MIr for static%n",member); ! 609: // if (i) i = i->typ(ftbl); ! 610: // Pname cn = member->tp->is_cl_obj(); // first find the class name ! 611: Pref tn = new ref(REF,f_this,member); ! 612: tn->tp = member->tp; ! 613: //error('d',"MI for %n %t = %t",member,member->tp,i?i->tp:0); ! 614: //error('d',"fthis %d %t member %n tp %t",f_this,f_this->tp,member,tn->tp); ! 615: if (cn) { ! 616: Pclass mcl = Pclass(cn->tp); // then find the classdef ! 617: Pname ctor = mcl->has_ctor(); ! 618: Pname icn; ! 619: ! 620: if (i ! 621: && mcl->has_itor()==0 ! 622: && (icn=i->tp->is_cl_obj()) ! 623: && Pclass(icn->tp)==mcl) { // bitwise copy ! 624: Pexpr init = new expr(ASSIGN,tn,i); ! 625: init->tp = tn->tp; ! 626: // return init->typ(ftbl); // don't look for mcl.operator=() ! 627: member->assign(); ! 628: return init; ! 629: } ! 630: ! 631: if (ctor) return call_ctor(ftbl,tn,ctor,i,DOT); ! 632: ! 633: error("Ir forM%nW noK",member); ! 634: return 0; ! 635: } ! 636: ! 637: if (cl_obj_vec) { ! 638: error('s',"Ir forCM arrayWK"); ! 639: return 0; ! 640: } ! 641: ! 642: if (i && i->base == ELIST) { ! 643: // if (i->base == ELIST) { ! 644: if (i->e2) error("Ir for%n not a simpleE",member); ! 645: i = i->e1; ! 646: } ! 647: ! 648: ! 649: // error( 'd', "fct_mem_init: %n %k", member, member->tp->base ); ! 650: ! 651: if (member->tp->is_ref() && ( i == 0 )) { ! 652: error( "empty Ir for reference %n", member ) ; ! 653: return 0 ; ! 654: } ! 655: switch (member->tp->base) { ! 656: /* Sam: this test is inadequate, since an RPTR can hide behind a */ ! 657: /* TNAME the new test above is the correct one */ ! 658: /* ! 659: case RPTR: ! 660: if ( i == 0 ) { ! 661: error( "empty Ir for reference %n", member ); ! 662: return 0; ! 663: } ! 664: break; ! 665: */ ! 666: case VEC: ! 667: case FCT: ! 668: case OVERLOAD: ! 669: error("Ir for%n ofT %t",member,member->tp); ! 670: return 0; ! 671: } ! 672: ! 673: //error('d',"tp %t",member->tp); ! 674: if (member->tp->tconst()) { ! 675: extern ignore_const; ! 676: int save_ignore_const = ignore_const; ! 677: ignore_const = 1; ! 678: i = new expr(ASSIGN,tn,i); ! 679: i = i->typ(ftbl); ! 680: ignore_const = save_ignore_const; ! 681: return i; ! 682: } ! 683: ! 684: Pptr pt; ! 685: if (pt = member->tp->is_ref()) { ! 686: switch (pt->typ->base) { ! 687: case FCT: ! 688: case OVERLOAD: ! 689: i = ptr_init(pt,i,ftbl); ! 690: break; ! 691: default: ! 692: i = ref_init(pt,i,ftbl); ! 693: } ! 694: i = new expr(ASSIGN,tn,i); ! 695: i->tp = tn->tp; ! 696: member->assign(); // cannot call typ: would cause dereference ! 697: return i; ! 698: } ! 699: ! 700: i = new expr(ASSIGN,tn,i); ! 701: return i->typ(ftbl); // typ performs the type check on the assignment ! 702: } ! 703: ! 704: Pexpr replace_temp(Pexpr e, Pexpr n) ! 705: /* ! 706: e is on the form ! 707: f(&temp,arg) , temp ! 708: or ! 709: &temp->ctor(arg) , temp ! 710: or ! 711: x->f(&temp,arg) , temp ! 712: change it to ! 713: f(n,arg) ! 714: or ! 715: n->ctor(arg) ! 716: */ ! 717: { ! 718: Pexpr c = e->e1; // f(&temp,arg) or &temp->ctor(args) ! 719: Pexpr ff = c->e1; ! 720: Pexpr a = c->e2; // maybe ELIST(&temp,arg) ! 721: Pexpr tmp = e->e2; ! 722: ! 723: //error('d',"suppress(%d %k) %n",tmp->base,tmp->base,tmp->base==NAME?tmp:0); ! 724: if (tmp->base==DEREF) tmp = tmp->e1; ! 725: if (tmp->base==CAST) tmp = tmp->e1; ! 726: if (tmp->base==ADDROF || tmp->base==G_ADDROF) tmp = tmp->e2; ! 727: if (tmp->base != NAME) return e; //error('i',"replace %k",tmp->base); ! 728: tmp->tp = any_type; // temporary not used: suppress it ! 729: ! 730: //error('d',"replace_temp(%k %k) c %k ff %k",e->base,n->base,c->base,ff->base); ! 731: switch (ff->base) { ! 732: case REF: ! 733: if (ff->e1->base==G_ADDROF && ff->e1->e2==tmp) ! 734: a = ff; // &tmp -> f() ! 735: break; ! 736: case DOT: ! 737: if (ff->e1->base==NAME && ff->e1==tmp) { ! 738: a = ff; // tmp . f() ! 739: a->base = REF; ! 740: } ! 741: break; ! 742: } ! 743: a->e1 = n; ! 744: return c; ! 745: } ! 746: ! 747: Pname classdef::has_ictor() ! 748: /* ! 749: does this class have a constructor taking no arguments? ! 750: */ ! 751: { ! 752: Pname c = has_ctor(); ! 753: if (c == 0) return 0; ! 754: ! 755: Pfct f = Pfct(c->tp); ! 756: ! 757: switch (f->base) { ! 758: default: ! 759: error('i',"%s: badK (%k)",string,c->tp->base); ! 760: ! 761: case FCT: ! 762: switch (f->nargs) { ! 763: case 0: return c; ! 764: default: if (f->argtype->n_initializer) return c; ! 765: } ! 766: return 0; ! 767: ! 768: case OVERLOAD: ! 769: { for (Plist l=Pgen(f)->fct_list; l; l=l->l) { ! 770: Pname n = l->f; ! 771: f = (Pfct)n->tp; ! 772: switch (f->nargs) { ! 773: case 0: return n; ! 774: default: if (f->argtype->n_initializer) return n; ! 775: } ! 776: } ! 777: return 0; ! 778: } ! 779: } ! 780: } ! 781: ! 782: int add_first; // fudge, use ctor arg instead ! 783: Pname gen::add(Pname n) ! 784: /* ! 785: add "n" to the tail of "fct_list" ! 786: (overloaded names are searched in declaration order) ! 787: ! 788: detect: multiple identical declarations ! 789: declaration after use ! 790: multiple definitions ! 791: */ ! 792: { ! 793: extern linkage; ! 794: Pfct f = Pfct(n->tp); ! 795: Pname nx; ! 796: //error('d',"add(%n) %d",n,add_first); ! 797: if (f->base != FCT) error("%n: overloaded nonF",n); ! 798: ! 799: if ( fct_list && (nx=find(f,1)) ) { ! 800: //error('d',"found %n %t",nx,nx->tp); ! 801: if (linkage && Pfct(nx->tp)->f_signature && Pfct(nx->tp)->f_signature[0]) ! 802: error("inconsistent linkage specifications for%n",n); ! 803: Nold = 1; ! 804: } ! 805: else { ! 806: //extern linkage; ! 807: if (add_first==0) ! 808: if (linkage==0 && f->f_signature==0) f->sign(); ! 809: //error('d',"signature: %d \"%s\" fct_list %d",f->f_signature,f->f_signature,fct_list); ! 810: nx = new name; ! 811: *nx = *n; ! 812: nx->n_gen_fct_name = n->string; ! 813: PERM(nx); ! 814: Nold = 0; ! 815: if (fct_list) { ! 816: int clink = f->f_signature==0 || *f->f_signature==0; // function with C linkage ! 817: Plist gl=fct_list; ! 818: for(;;) { ! 819: if (clink ! 820: && (Pfct(gl->f->tp)->f_signature==0 ! 821: || *Pfct(gl->f->tp)->f_signature==0)) { ! 822: error("two%ns with c linkage",n); ! 823: f->sign(); ! 824: } ! 825: if (gl->l) ! 826: gl = gl->l; ! 827: else ! 828: break; ! 829: } ! 830: gl->l = new name_list(nx,0); ! 831: } ! 832: else ! 833: fct_list = new name_list(nx,0); ! 834: nx->n_list = 0; ! 835: } ! 836: return nx; ! 837: } ! 838: ! 839: void fct::sign() ! 840: { ! 841: char buf[1024]; ! 842: char* bb = signature(buf); ! 843: int ll = bb-buf; ! 844: if (1023 < ll) error('i',"gen::add():N buffer overflow"); ! 845: char* p = new char[ll+1]; ! 846: strcpy(p,buf); ! 847: f_signature = p; ! 848: //error('d',"fct::sign %s",p); ! 849: } ! 850: ! 851: Pname gen::find(Pfct f, bit warn) ! 852: { ! 853: for (Plist gl=fct_list; gl; gl=gl->l) { ! 854: Pname n = match(gl->f,f,warn); ! 855: if (n) return n; ! 856: } ! 857: return 0; ! 858: } ! 859: ! 860: Pname gen::match(Pname nx, Pfct f, bit warn) ! 861: { ! 862: Pfct fx = Pfct(nx->tp); ! 863: Pname a, ax; ! 864: int op = 0; // overloading problem: const, ref, vec/ptr, or basetype ! 865: //error('d',"fx %d %d f %d %d",fx->nargs_known,fx->nargs,f->nargs_known,f->nargs); ! 866: ! 867: if (f->nargs_known != fx->nargs_known) return 0; // the bets are off ! 868: // must rely on checks at ! 869: // call points ! 870: if (f->f_const != fx->f_const) return 0; ! 871: ! 872: if (fx->nargs != f->nargs ! 873: && fx->nargs_known==1 ! 874: && f->nargs_known==1) return 0; // no warning for potential ! 875: // problems due to default args ! 876: ! 877: for (ax=fx->argtype, a=f->argtype; a&&ax; ax=ax->n_list, a=a->n_list) { ! 878: Ptype at = ax->tp; ! 879: Ptype atp = a->tp; ! 880: //error('d',"at %t atp %t",at,atp); ! 881: if (at->check(atp,OVERLOAD) == 0) { ! 882: //error('d',"at %t atp %t cp %d vrp %d",at,atp,const_problem,vrp_equiv); ! 883: // if (vrp_equiv) op++; // or differ only by [] vs * ! 884: continue; ! 885: } ! 886: //error('d',"warn %d",warn); ! 887: if (warn == 0) goto xx; ! 888: ! 889: /* ! 890: warn against: ! 891: overload f(X&), f(X); error ! 892: overload f(int), f(const); error ! 893: overload f(int*), f(int[10]); warn ! 894: etc. ! 895: */ ! 896: ! 897: //error('d',"vrp_equiv %d const_problem %d",vrp_equiv,const_problem); ! 898: if (const_problem) { // differ only in X vs const X ! 899: if (at->is_ptr_or_ref()) return 0; ! 900: op++; ! 901: continue; ! 902: } ! 903: ! 904: aaa: ! 905: switch (atp->base) { ! 906: case TYPE: ! 907: atp = Pbase(atp)->b_name->tp; ! 908: goto aaa; ! 909: // case EOBJ: ! 910: // atp = Penum(Pbase(atp)->b_name->tp)->e_type; ! 911: // goto aaa; ! 912: case RPTR: // differ only by X vs X& ? ! 913: if (Pptr(atp)->typ->check(at,0)==0) { ! 914: op++; ! 915: continue; ! 916: } ! 917: } ! 918: ! 919: atl: ! 920: switch (at->base) { ! 921: case TYPE: ! 922: at = Pbase(at)->b_name->tp; ! 923: goto atl; ! 924: // case EOBJ: ! 925: // at = Penum(Pbase(at)->b_name->tp)->e_type; ! 926: // goto atl; ! 927: case RPTR: // differ only by X& vs X ? ! 928: if (Pptr(at)->typ->check(atp,0)==0) { ! 929: op++; ! 930: continue; ! 931: } ! 932: break; ! 933: // case CHAR: // differ only by int vs char ? ! 934: // case SHORT: ! 935: // case INT: ! 936: // if (atp->base!=at->base && atp->base==EOBJ) { ! 937: // op++; ! 938: // continue; ! 939: // } ! 940: // break; ! 941: } ! 942: //error('d',"return 0"); ! 943: //goto xx; ! 944: // some argument is really different ! 945: // e.g. f(int), f(char*); ! 946: return 0; ! 947: } ! 948: ! 949: // arguments checked. Now look at leftover args, return type,etc. ! 950: ! 951: // if (warn && a && fx->nargs_known==ELLIPSIS) error('w',"... in%n'sAT hidesATs from the overloading mechanism",nx); ! 952: ! 953: if (a || ax) return 0; ! 954: ! 955: if (op == 0) { ! 956: if (warn && fx->returns->check(f->returns,0)) ! 957: error("two different return valueTs for%n: %t and %t",nx,fx->returns,f->returns); ! 958: ! 959: return nx; ! 960: } ! 961: xx: ! 962: if (warn && op) ! 963: error("the overloading mechanism cannot tell a%t from a%t",fx,f); ! 964: ! 965: return 0; ! 966: } ! 967: ! 968: int name::no_of_names() ! 969: { ! 970: register int i = 0; ! 971: register Pname n; ! 972: for (n=this; n; n=n->n_list) i++; ! 973: return i; ! 974: } ! 975: ! 976: static Pexpr lvec[20], *lll, *curr_e; ! 977: static Pexpr list_back = 0; ! 978: ! 979: void new_list(Pexpr lx) ! 980: { ! 981: if (lx->base != ILIST) error('i',"IrLX"); ! 982: ! 983: lll = lvec; ! 984: lll++; ! 985: *lll = lx->e1; ! 986: } ! 987: ! 988: Pexpr next_elem() ! 989: { ! 990: Pexpr e; ! 991: Pexpr lx; ! 992: ! 993: if (lll == lvec) return 0; ! 994: ! 995: lx = *lll; ! 996: ! 997: if (list_back) { ! 998: e = list_back; ! 999: list_back = 0; ! 1000: return e; ! 1001: } ! 1002: ! 1003: if (lx == 0) { /* end of list */ ! 1004: lll--; ! 1005: return 0; ! 1006: } ! 1007: ! 1008: switch (lx->base) { ! 1009: case ELIST: ! 1010: e = lx->e1; ! 1011: curr_e = &lx->e1; ! 1012: *lll = lx->e2; ! 1013: switch (e->base) { ! 1014: case ILIST: ! 1015: lll++; ! 1016: *lll = e->e1; ! 1017: return Pexpr(1); // start of new ILIST ! 1018: case ELIST: ! 1019: error("nestedEL"); ! 1020: return 0; ! 1021: default: ! 1022: { ! 1023: int need_sti(Pexpr, Ptable tbl = 0); ! 1024: if (need_sti(e)) error('s',"generalIr inIrL"); ! 1025: return e; ! 1026: } ! 1027: } ! 1028: case IVAL: ! 1029: case ZERO: ! 1030: lll--; ! 1031: return 0; ! 1032: default: ! 1033: error('i',"IrL %k",lx->base); ! 1034: } ! 1035: } ! 1036: ! 1037: void skip_ilist() ! 1038: // skip ilist use to represent pointer to member function literal ! 1039: { ! 1040: Pexpr e = next_elem(); ! 1041: e = next_elem(); ! 1042: } ! 1043: ! 1044: void list_check(Pname nn, Ptype t, Pexpr il) ! 1045: /* ! 1046: see if the list "lll" can be assigned to something of type "t" ! 1047: "nn" is the name of the variable for which the assignment is taking place. ! 1048: "il" is the last list element returned by next_elem() ! 1049: */ ! 1050: { ! 1051: Pexpr e; ! 1052: bit lst = 0; ! 1053: int i; ! 1054: Pclass cl; ! 1055: int tdef = 0; ! 1056: ! 1057: //error('d',"list_check%n: %t (%d)",nn,t,il); ! 1058: if (il == Pexpr(1)) ! 1059: lst = 1; ! 1060: else if (il) ! 1061: list_back = il; ! 1062: ! 1063: zzz: ! 1064: switch (t->base) { ! 1065: case TYPE: ! 1066: t = Pbase(t)->b_name->tp; ! 1067: tdef = 1; ! 1068: goto zzz; ! 1069: ! 1070: case VEC: ! 1071: { Pvec v = Pvec(t); ! 1072: Ptype vt = v->typ; ! 1073: ! 1074: if (v->size) { /* get at most v->size initializers */ ! 1075: if (v->typ->base == CHAR) { ! 1076: e = next_elem(); ! 1077: if (e->base == STRING) { // v[size] = "..." ! 1078: int isz = Pvec(e->tp)->size; ! 1079: if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size); ! 1080: break; ! 1081: } ! 1082: else ! 1083: list_back = e; ! 1084: } ! 1085: for (i=0; i<v->size; i++) { // check next list element type ! 1086: ee: ! 1087: e = next_elem(); ! 1088: if (e == 0) goto xsw; // too few initializers are ok ! 1089: vtz: ! 1090: //error('d',"vtz: %d",vt->base); ! 1091: switch (vt->base) { ! 1092: case TYPE: ! 1093: vt = Pbase(vt)->b_name->tp; ! 1094: goto vtz; ! 1095: case VEC: ! 1096: case COBJ: ! 1097: list_check(nn,vt,e); ! 1098: break; ! 1099: case PTR: ! 1100: if (Pptr(vt)->memof ! 1101: && Pptr(vt)->typ->base==FCT ! 1102: && e==Pexpr(1)) { ! 1103: skip_ilist(); ! 1104: break; ! 1105: } ! 1106: // no break ! 1107: default: ! 1108: { ! 1109: if (e == (Pexpr)1) { ! 1110: error("unexpectedIrL"); ! 1111: goto ee; ! 1112: } ! 1113: ! 1114: if (vt->check(e->tp,ASSIGN)) ! 1115: error("badIrT for%n:%t (%tX)",nn,e->tp,vt); ! 1116: ! 1117: Pptr p; ! 1118: if (vt->check(e->tp,0) ! 1119: && (p=vt->is_ptr()) ! 1120: && Ptype(p)!=zero_type ! 1121: && p->typ!=char_type) ! 1122: *curr_e = new cast(vt,e); ! 1123: } ! 1124: } ! 1125: } ! 1126: if ( lst && (e=next_elem()) ) error("end ofIrLX after array"); ! 1127: xsw:; ! 1128: } ! 1129: else { /* determine v->size */ ! 1130: i = 0; ! 1131: (void) v->typ->tsizeof(); ! 1132: xx: ! 1133: while ( e=next_elem() ) { // get another initializer ! 1134: i++; ! 1135: vtzz: ! 1136: //error('d',"vtzz"); ! 1137: switch (vt->base) { ! 1138: case TYPE: ! 1139: vt = Pbase(vt)->b_name->tp; ! 1140: goto vtzz; ! 1141: case VEC: ! 1142: case COBJ: ! 1143: list_check(nn,vt,e); ! 1144: break; ! 1145: case PTR: ! 1146: if (Pptr(vt)->memof ! 1147: && Pptr(vt)->typ->base==FCT ! 1148: && e==Pexpr(1)) { ! 1149: skip_ilist(); ! 1150: break; ! 1151: } ! 1152: // no break ! 1153: default: ! 1154: { if (e == Pexpr(1)) { ! 1155: error("unexpectedIrL"); ! 1156: goto xx; ! 1157: } ! 1158: ! 1159: if (vt->check(e->tp,ASSIGN)) ! 1160: error("badIrT for%n:%t (%tX)",nn,e->tp,vt); ! 1161: ! 1162: Pptr p; ! 1163: if (vt->check(e->tp,0) ! 1164: && (p=vt->is_ptr()) ! 1165: && Ptype(p)!=zero_type ! 1166: && p->typ!=char_type) ! 1167: *curr_e = new cast(vt,e); ! 1168: } ! 1169: } ! 1170: } ! 1171: if (tdef==0) v->size = i; ! 1172: } ! 1173: break; ! 1174: } ! 1175: ! 1176: case CLASS: ! 1177: cl = Pclass(t); ! 1178: goto ccc; ! 1179: ! 1180: case COBJ: /* initialize members */ ! 1181: cl = Pclass(Pbase(t)->b_name->tp); ! 1182: ccc: ! 1183: if (cl->defined == 0) { ! 1184: lll = lvec; // we are lost: ignore rest of list ! 1185: return; ! 1186: } ! 1187: ! 1188: if (cl->c_body == 1) cl->dcl_print(0); ! 1189: ! 1190: { Ptable tbl = cl->memtbl; ! 1191: Pname m; ! 1192: ! 1193: if (cl->baselist) { ! 1194: if (cl->baselist->next) error("IrL forO ofC with multipleBCs"); ! 1195: list_check(nn,cl->baselist->bclass,0); ! 1196: } ! 1197: ! 1198: for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) { ! 1199: Ptype mt = m->tp; ! 1200: switch (mt->base) { ! 1201: case FCT: ! 1202: case OVERLOAD: ! 1203: case CLASS: ! 1204: case ENUM: ! 1205: continue; ! 1206: } ! 1207: if (m->n_stclass == STATIC) continue; ! 1208: /* check assignment to next member */ ! 1209: dd: ! 1210: e = next_elem(); ! 1211: if (e == 0) return; //break; ! 1212: mtz: ! 1213: //error('d',"mtz%n: %d",m,mt->base); ! 1214: switch (mt->base) { ! 1215: case TYPE: ! 1216: mt = Pbase(mt)->b_name->tp; ! 1217: goto mtz; ! 1218: case CLASS: ! 1219: case ENUM: ! 1220: break; ! 1221: case VEC: ! 1222: case COBJ: ! 1223: list_check(nn,m->tp,e); ! 1224: break; ! 1225: case PTR: ! 1226: if (Pptr(mt)->memof ! 1227: && Pptr(mt)->typ->base==FCT ! 1228: && e==Pexpr(1)) { ! 1229: skip_ilist(); ! 1230: break; ! 1231: } ! 1232: // no break ! 1233: default: ! 1234: { if (e == Pexpr(1)) { ! 1235: error("unexpectedIrL"); ! 1236: goto dd; ! 1237: } ! 1238: ! 1239: if (mt->check(e->tp,ASSIGN)) ! 1240: error("badIrT for%n:%t (%tX)",m,e->tp,m->tp); ! 1241: ! 1242: Pptr p; ! 1243: if (mt->check(e->tp,0) ! 1244: && (p=mt->is_ptr()) ! 1245: && Ptype(p)!=zero_type ! 1246: && p->typ!=char_type) ! 1247: *curr_e = new cast(mt,e); ! 1248: } ! 1249: } ! 1250: } ! 1251: if (lst && (e=next_elem()) ) error("end ofIrLX afterCO"); ! 1252: break; ! 1253: } ! 1254: default: ! 1255: e = next_elem(); ! 1256: ! 1257: if (e == 0) { ! 1258: error("noIr forO"); ! 1259: break; ! 1260: } ! 1261: ! 1262: if (e == Pexpr(1)) { ! 1263: error("unexpectedIrL"); ! 1264: break; ! 1265: } ! 1266: //error('d',"t %t e->tp %t",t,e->tp); ! 1267: if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t); ! 1268: Pptr p; ! 1269: if (t->check(e->tp,0) ! 1270: && (p=t->is_ptr()) ! 1271: && Ptype(p)!=zero_type ! 1272: && p->typ!=char_type) ! 1273: *curr_e = new cast(t,e); ! 1274: if (lst && (e=next_elem()) ) error("end ofIrLX afterO"); ! 1275: break; ! 1276: } ! 1277: } ! 1278: ! 1279: Pname dclass(Pname n, Ptable tbl) ! 1280: { ! 1281: Pclass cl; ! 1282: Pbase bt; ! 1283: Pname bn; ! 1284: TOK t; ! 1285: ! 1286: //local class ! 1287: Pname nx = ktbl->look(n->string,0); // TNAME ! 1288: // error( 'd', "dclass n %n %d nx %d", n,n->lex_level, nx); ! 1289: if (nx == 0 || n->lex_level ) { ! 1290: /* search for hidden name for ! 1291: (1) nested class declaration ! 1292: (2) local class declaration ! 1293: */ ! 1294: int tn = 0; ! 1295: t = n->lex_level ? LOCAL : HIDDEN; ! 1296: // error( 'd', "dclass t: %k", t ); ! 1297: for (nx=ktbl->look(n->string,t); nx; nx=nx->n_tbl_list) { ! 1298: // error('d',"dclass: %n %t t: %s",n,n->tp, t==LOCAL?"Local":"Hidden"); ! 1299: // error('d',"dclass: nx: %s %k t: %s",nx->string,nx->tp->base, t==LOCAL?"Local":"Hidden"); ! 1300: if (nx->n_key != t) continue; ! 1301: if ( nx->lex_level != n->lex_level ) continue; ! 1302: ! 1303: if (nx->tp->base != COBJ) { ! 1304: tn = 1; ! 1305: continue; ! 1306: } ! 1307: ! 1308: ! 1309: bt = (Pbase)nx->tp; ! 1310: bn = bt->b_name; ! 1311: cl = (Pclass)bn->tp; ! 1312: ! 1313: if (cl == 0) continue; ! 1314: ! 1315: if ( n->lex_level && ! 1316: (cl->lcl==0 || strcmp(cl->lcl,Pclass(n->tp)->lcl))) continue; ! 1317: //error('d',"goto bbb"); ! 1318: goto bbb; ! 1319: } ! 1320: ! 1321: if (tn) ! 1322: error("%n redefined using typedef",n); ! 1323: else ! 1324: error('i',"%n is not aCN",n); ! 1325: } ! 1326: else { ! 1327: bt = Pbase(nx->tp); // COBJ ! 1328: // error ('d', "dclass: bt->base: %k", bt->base ); ! 1329: if ( bt->base != COBJ ) { ! 1330: error("%n redefined using typedef",n); ! 1331: Pname tn = ktbl->look(n->string,HIDDEN); ! 1332: // error( 'd', "dclass: tn: %t", tn ); ! 1333: if ( tn->tp->base == COBJ ) ! 1334: bt = Pbase(tn->tp); ! 1335: else error('i',"%n is not a CN", n ); ! 1336: } ! 1337: bn = bt->b_name; ! 1338: } ! 1339: bbb: ! 1340: Pname ln = tbl->look(bn->string,0); ! 1341: // if (ln && ln->n_table==tbl) error('w',"%n redefined",ln); ! 1342: //error('d',"ln %n",ln); ! 1343: bn->where = nx->where; ! 1344: Pname bnn = tbl->insert(bn,CLASS); // copy for member lookup ! 1345: cl = Pclass(bn->tp); ! 1346: if (cl->class_base == template_class) ! 1347: error ("class %n was previously defined as a template class", ! 1348: bn) ; ! 1349: // CLASS ! 1350: if (cl->defined&(DEFINED|SIMPLIFIED)) ! 1351: error("C%n defined twice",n); ! 1352: else { ! 1353: if (bn->n_scope == ARG) bn->n_scope = ARGT; ! 1354: cl->dcl(bn,tbl); ! 1355: } ! 1356: n->tp = cl; ! 1357: //error('d'," -> "); ! 1358: return bnn; ! 1359: } ! 1360: ! 1361: Pname denum(Pname n, Ptable tbl) ! 1362: { ! 1363: Pname nx = ktbl->look(n->string,0); // TNAME ! 1364: if (nx == 0) nx = ktbl->look(n->string,HIDDEN); // hidden TNAME ! 1365: Pbase bt = (Pbase)nx->tp; // EOBJ ! 1366: Pname bn = bt->b_name; ! 1367: Pname bnn = tbl->insert(bn,CLASS); ! 1368: Penum en = (Penum)bn->tp; // ENUM ! 1369: if (en->defined&(DEFINED|SIMPLIFIED)) ! 1370: error("enum%n defined twice",n); ! 1371: else { ! 1372: if (bn->n_scope == ARG) bn->n_scope = ARGT; ! 1373: en->dcl(bn,tbl); ! 1374: } ! 1375: n->tp = en; ! 1376: return bnn; ! 1377: } ! 1378: ! 1379: void dargs(Pname, Pfct f, Ptable tbl) ! 1380: { ! 1381: int oo = const_save; ! 1382: const_save = 1; ! 1383: ! 1384: for (Pname a=f->argtype; a; a=a->n_list) { ! 1385: Pexpr init; ! 1386: ! 1387: if (a->tp == 0) { ! 1388: error( "A has noT" ); ! 1389: a->tp = any_type; ! 1390: continue; ! 1391: } ! 1392: ! 1393: Pname cln = a->tp->is_cl_obj(); ! 1394: //error('d',"dargs %t",a->tp); ! 1395: if (cln && Pclass(cln->tp)->has_itor()) // mark X(X&) arguments ! 1396: a->n_xref = 1; ! 1397: else { ! 1398: Ptype t = a->tp; ! 1399: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 1400: if (t->base == FCT) a->tp = new ptr(PTR,a->tp); ! 1401: } ! 1402: ! 1403: if (init = a->n_initializer) { // default argument ! 1404: Pptr pt; ! 1405: if (init == dummy) { ! 1406: error("emptyIr"); ! 1407: a->n_initializer = 0; ! 1408: continue; ! 1409: } ! 1410: if (cln) { ! 1411: if (init->base==VALUE) { ! 1412: switch (init->tp2->base) { ! 1413: case CLASS: ! 1414: if (Pclass(init->tp2)!=Pclass(cln->tp)) goto inin2; ! 1415: break; ! 1416: default: ! 1417: Pname n2 = init->tp2->is_cl_obj(); ! 1418: if (n2==0 || Pclass(n2->tp)!=Pclass(cln->tp)) goto inin2; ! 1419: } ! 1420: ! 1421: a->n_initializer = init = 0; ! 1422: error('s',"K as defaultA"); ! 1423: } ! 1424: else { ! 1425: inin2: ! 1426: if (init->base == ILIST) error("list as AIr"); ! 1427: Pexpr i = init->typ(tbl); ! 1428: init = class_init(a,a->tp,i,tbl); ! 1429: if (i!=init && init->base==DEREF) { ! 1430: error('s',"K needed forAIr"); ! 1431: init = 0; ! 1432: } ! 1433: else { ! 1434: void dosimpl(Pexpr,Pname); ! 1435: dosimpl(init,cc->nof); ! 1436: // init->simpl(); ! 1437: init->permanent = 2; ! 1438: } ! 1439: a->n_initializer = init; ! 1440: } ! 1441: } ! 1442: else if (pt = a->tp->is_ref()) { ! 1443: extern ref_initializer; ! 1444: ref_initializer++; ! 1445: init = init->typ(tbl); ! 1446: ref_initializer--; ! 1447: int tcount = stcount; ! 1448: init = ref_init(pt,init,tbl); ! 1449: if (tcount != stcount) { ! 1450: error('s',"needs temporaryV to evaluateAIr"); ! 1451: init = 0; ! 1452: } ! 1453: else { ! 1454: void dosimpl(Pexpr,Pname); ! 1455: dosimpl(init,cc->nof); ! 1456: // init->simpl(); ! 1457: init->permanent = 2; ! 1458: } ! 1459: a->n_initializer = init; ! 1460: } ! 1461: else { ! 1462: Pptr p = a->tp->is_ptr(); ! 1463: init = init->typ(tbl); ! 1464: if (p) init = ptr_init(p,init,tbl); ! 1465: ! 1466: if (a->tp->check(init->tp,ARG)) { ! 1467: int i = can_coerce(a->tp,init->tp); ! 1468: ! 1469: switch (i) { ! 1470: case 1: ! 1471: if (Ncoerce) { ! 1472: Pname cn = init->tp->is_cl_obj(); Pname xx = new name(Ncoerce->string); ! 1473: Pref r = new ref(DOT,init,xx); ! 1474: init = new expr(G_CALL,r,0); ! 1475: init = init->typ(tbl); ! 1476: } ! 1477: break; ! 1478: default: ! 1479: error("%d possible conversions for defaultA",i); ! 1480: case 0: ! 1481: error("badIrT%t forA%n",init->tp,a); ! 1482: DEL(init); ! 1483: a->n_initializer = init = 0; ! 1484: } ! 1485: } ! 1486: ! 1487: if (init) { ! 1488: void dosimpl(Pexpr,Pname); ! 1489: dosimpl(init,cc->nof); ! 1490: // init->simpl(); ! 1491: init->permanent = 2; ! 1492: a->n_initializer = init; ! 1493: Neval = 0; ! 1494: long i = init->eval(); ! 1495: if (Neval == 0) { ! 1496: a->n_evaluated = 1; ! 1497: a->n_val = i; ! 1498: } ! 1499: } ! 1500: } ! 1501: } ! 1502: } ! 1503: const_save = oo; ! 1504: } ! 1505: ! 1506: void merge_init(Pname nn, Pfct f, Pfct nf) ! 1507: { ! 1508: // Pname a1 = f->f_args; if (a1==0) a1 = f->argtype; ! 1509: // Pname a2 = nf->f_args;//nf->argtype; ! 1510: Pname a1 = f->argtype; ! 1511: Pname a2 = nf->argtype; ! 1512: ! 1513: for (; a1; a1=a1->n_list, a2=a2->n_list) { ! 1514: int i1 = a1->n_initializer || a1->n_evaluated; ! 1515: int i2 = a2->n_initializer || a2->n_evaluated; ! 1516: ! 1517: if (i1 && i2) error(&a1->where,"twoIrs for%nA%n",nn,a1); ! 1518: ! 1519: if (i1) { ! 1520: a2->n_initializer = a1->n_initializer; ! 1521: a2->n_evaluated = a1->n_evaluated; ! 1522: a2->n_val = a1->n_val; ! 1523: } ! 1524: if (i2) { ! 1525: a1->n_initializer = a2->n_initializer; ! 1526: a1->n_evaluated = a2->n_evaluated; ! 1527: a1->n_val = a2->n_val; ! 1528: } ! 1529: ! 1530: } ! 1531: } ! 1532: ! 1533: Pexpr try_to_coerce(Ptype rt, Pexpr e, char* s, Ptable tbl) ! 1534: /* ! 1535: ``e'' is of class ``cn'' coerce it to type ``rt'' ! 1536: */ ! 1537: { ! 1538: int i; ! 1539: Pname cn; ! 1540: //error('d',"try_to_coerce(%t, %t, %s, %d)",rt,e->tp,s,tbl); ! 1541: ! 1542: if ((cn=e->tp->is_cl_obj()) && (i=can_coerce(rt,e->tp)) && Ncoerce) { ! 1543: if (1 < i) error("%d possible conversions for %s",i,s); ! 1544: //error('d',"coerce %n",Ncoerce); ! 1545: Pclass cl = Pclass(cn->tp); ! 1546: // Pref r = new ref(DOT,e,Ncoerce); ! 1547: // Pexpr rr = r->typ(tbl); ! 1548: // Pexpr c = new expr(G_CALL,rr,0); ! 1549: // c->fct_name = Ncoerce; ! 1550: Pname xx = new name(Ncoerce->string); ! 1551: Pref r = new ref(DOT,e,xx); ! 1552: Pexpr c = new expr(G_CALL,r,0); ! 1553: // return c->typ(tbl); ! 1554: c = c->typ(tbl); ! 1555: //error('d',"coerce -> %k %t",c->base,c->tp); ! 1556: ! 1557: return c; ! 1558: } ! 1559: //error('d',"coerce ->0"); ! 1560: return 0; ! 1561: } ! 1562: ! 1563: int in_class_dcl; ! 1564: ! 1565: Pname name::dofct(Ptable tbl, TOK scope) ! 1566: { ! 1567: Pfct f = Pfct(tp); ! 1568: Pname class_name; ! 1569: Ptable etbl; ! 1570: in_class_dcl = cc->not!=0; ! 1571: int just_made = 0; ! 1572: // int fvirt = 0; //BSopt ! 1573: //error('d',"dofct %n %d %t %s",this,tp,tp,tbl==gtbl?"global":""); ! 1574: ! 1575: if (f->f_inline) n_sto = STATIC; ! 1576: ! 1577: if (n_stclass) ! 1578: switch (n_stclass) { ! 1579: case EXTERN: ! 1580: case STATIC: ! 1581: case OVERLOAD: ! 1582: break; ! 1583: default: ! 1584: error("%n declared%k",this,n_stclass); ! 1585: n_stclass = EXTERN; ! 1586: } ! 1587: ! 1588: tp->dcl(tbl); // must be done before the type check ! 1589: ! 1590: if (n_qualifier) { // qualified name: c::f() checked above ! 1591: // ineffective ! 1592: // if (in_class_dcl) { ! 1593: // error("unexpectedQdN%n",this); ! 1594: // return 0; ! 1595: // } ! 1596: ! 1597: if (f->f_virtual) { ! 1598: error("virtual outsideCD (ignored)"); ! 1599: f->f_virtual = 0; ! 1600: } ! 1601: ! 1602: if (n_sto ! 1603: && n_sto!=FRIEND // friend X::f(); ! 1604: && f->f_inline==0) { // inline causes n_sto==STATIC ! 1605: error("%k specifed for QdN%n",n_sto,this); ! 1606: n_sto = 0; ! 1607: } ! 1608: ! 1609: class_name = Pbase(n_qualifier->tp)->b_name; ! 1610: etbl = Pclass(class_name->tp)->memtbl; ! 1611: } ! 1612: else { ! 1613: class_name = cc->not; ! 1614: // beware of local function declarations in member functions ! 1615: if (class_name && tbl!=cc->cot->memtbl) { ! 1616: class_name = 0; ! 1617: in_class_dcl = 0; ! 1618: } ! 1619: ! 1620: if (f->f_static && f->f_virtual) { ! 1621: error("virtual staticM"); ! 1622: f->f_virtual = 0; ! 1623: } ! 1624: ! 1625: if (n_oper) check_oper(class_name); ! 1626: etbl = tbl; ! 1627: } ! 1628: ! 1629: // Pfct(tp)->memof = class_name ? Pclass(class_name->tp) : 0; ! 1630: ! 1631: Pname find_virtual(Pclass,Pname); ! 1632: ! 1633: if (class_name) { ! 1634: f->memof = Pclass(class_name->tp); ! 1635: if (f->f_virtual==0 && find_virtual(f->memof,this)) ! 1636: f->f_virtual = VTOK; ! 1637: } ! 1638: ! 1639: if (etbl==0 || etbl->base!=TABLE) error('i',"N::dcl: etbl=%d",etbl); ! 1640: ! 1641: switch (n_oper) { ! 1642: case CTOR: ! 1643: if (f->f_virtual) { ! 1644: error("virtualK"); ! 1645: f->f_virtual = 0; ! 1646: } ! 1647: ! 1648: // case DTOR: ! 1649: // f->f_const = 1; ! 1650: break; ! 1651: ! 1652: case REF: ! 1653: if (f->argtype) ! 1654: error("%n takes no argument",this); ! 1655: else if (f->returns->is_ptr() == 0) { ! 1656: Pname cn = f->returns->is_cl_obj(); ! 1657: if (cn==0 && f->returns->base==RPTR) cn = Pptr(f->returns)->typ->is_cl_obj(); ! 1658: if (cn==0 || Pclass(cn->tp)->has_oper(REF)==0) ! 1659: error("%n must return aP toCO, aR toCO, or aCO",this); ! 1660: } ! 1661: break; ! 1662: ! 1663: case NEW: // void* operator new(long) ! 1664: if (f->f_virtual) ! 1665: error("virtual%n (operator new() is static)",this); ! 1666: if (class_name) f->f_static = 1; // if member: static by default ! 1667: if (f->nargs_known != 1) ! 1668: error("ATs must be fully specified for%n",this); ! 1669: else if (f->nargs<1) ! 1670: error("%n requires a firstA ofT size_t",this); ! 1671: else if (f->argtype->tp->check(size_t_type,0)) { ! 1672: if (strict_opt==0 ! 1673: && f->argtype->tp->check(long_type,0)==0) { ! 1674: error('w',"%n firstA should be size_t",this); ! 1675: f->argtype->tp = size_t_type; ! 1676: if (f->f_signature) f->sign(); ! 1677: } ! 1678: else ! 1679: error("%n requires a firstA ofT size_t",this); ! 1680: } ! 1681: else { ! 1682: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 1683: if (t->check(Pvoid_type,0)) error("bad returnT for %n",this); ! 1684: } ! 1685: break; ! 1686: ! 1687: case DELETE: // void operator delete(void*) or ! 1688: // void operator delete(void*, long) ! 1689: if (f->f_virtual) ! 1690: error("virtual%n (operator delete() is static)",this); ! 1691: if (class_name) f->f_static = 1; // if member: static by default ! 1692: if (f->nargs_known != 1) ! 1693: error("ATs must be fully specified for%n",this); ! 1694: else { ! 1695: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 1696: if (t->base != VOID) ! 1697: error("bad returnT for %n", this); ! 1698: else { ! 1699: switch (f->nargs) { ! 1700: default: ! 1701: error("%n takes 1 or 2As",this); ! 1702: break; ! 1703: case 1: ! 1704: case 2: ! 1705: { Pname a = f->argtype; ! 1706: if (a->tp->check(Pvoid_type,0)) ! 1707: error("%n's 1stA must be a void*",this); ! 1708: else if (a = a->n_list) { ! 1709: if (class_name == 0) ! 1710: error("%n takes only oneA",this); ! 1711: else if (a->tp->check(size_t_type,0)) { ! 1712: if (strict_opt==0 ! 1713: && a->tp->check(long_type,0)==0) { ! 1714: error('w',"%n's 2ndA should be a size_t",this); ! 1715: a->tp = size_t_type; ! 1716: if (f->f_signature) f->sign(); ! 1717: } ! 1718: else ! 1719: error("%n's 2ndA must be a size_t",this); ! 1720: } ! 1721: } ! 1722: } ! 1723: } ! 1724: } ! 1725: } ! 1726: break; ! 1727: ! 1728: case ASSIGN: ! 1729: if (class_name && f->nargs==1) { ! 1730: Ptype t = f->argtype->tp; ! 1731: Pname an = t->is_cl_obj(); // X::operator=(X) ? ! 1732: if (an==0 && (t=t->is_ref())) { // X::operator=(X&) ? ! 1733: t = Pptr(t)->typ; ! 1734: rx1: ! 1735: switch (t->base) { ! 1736: case TYPE: t = Pbase(t)->b_name->tp; goto rx1; ! 1737: case COBJ: an = Pbase(t)->b_name; ! 1738: } ! 1739: } ! 1740: if (an && an==class_name) Pclass(an->tp)->c_xref |= C_ASS; ! 1741: } ! 1742: else if (f->nargs == 2) { ! 1743: Ptype t = f->argtype->tp; ! 1744: Pname an1; ! 1745: if (t=t->is_ref()) { // operator=(X&,?) ? ! 1746: t = Pptr(t)->typ; ! 1747: rx2: ! 1748: switch (t->base) { ! 1749: case TYPE: t = Pbase(t)->b_name->tp; goto rx2; ! 1750: case COBJ: an1 = Pbase(t)->b_name; ! 1751: } ! 1752: } ! 1753: t = f->argtype->n_list->tp; ! 1754: Pname an2 = t->is_cl_obj(); // operator=(X&,X) ? ! 1755: if (an2==0 && (t=t->is_ref())) { // operator=(X&,X&) ? ! 1756: t = Pptr(t)->typ; ! 1757: rx3: ! 1758: switch (t->base) { ! 1759: case TYPE: t = Pbase(t)->b_name->tp; goto rx3; ! 1760: case COBJ: an2 = Pbase(t)->b_name; ! 1761: } ! 1762: } ! 1763: if (an1 && an1==an2) Pclass(an1->tp)->c_xref |= C_ASS; ! 1764: } ! 1765: } ! 1766: ! 1767: switch (scope) { ! 1768: case FCT: ! 1769: case ARG: ! 1770: if (n_sto == STATIC) error("D of staticF in aF"); ! 1771: } ! 1772: ! 1773: Pname nn = etbl->insert(this,0); ! 1774: nn->assign(); ! 1775: n_table = etbl; ! 1776: //error('d',"nn %n %t %d %d",nn,nn->tp,nn->tp,f); ! 1777: ! 1778: if (n_initializer) { ! 1779: if (f->f_virtual == 0) error("Ir for non-virtualF%n",this); ! 1780: if (n_initializer != zero) error("virtualFIr must be 0"); ! 1781: } ! 1782: ! 1783: if (Nold) { ! 1784: Pfct nf = Pfct(nn->tp); ! 1785: //error('d',"old %n: %t and %t",nn,nf,tp); ! 1786: if (nf->base==ANY || f->base==ANY) ! 1787: ; ! 1788: else if (nf->base == OVERLOAD) { ! 1789: string = nn->string; ! 1790: nn = Pgen(nf)->add(this); ! 1791: ! 1792: if (Nold == 0) { ! 1793: if (f->body && n_qualifier) { ! 1794: error("badAL for %n::%s()",n_qualifier,string); ! 1795: return 0; ! 1796: } ! 1797: goto thth; ! 1798: } ! 1799: // else { ! 1800: // if (f->body==0 && friend_in_class==0) error('w',"%n redeclared",nn); ! 1801: // } ! 1802: ! 1803: nf = Pfct(nn->tp); ! 1804: ! 1805: if (nf->body && f->body) { ! 1806: // Preserve the original definition in the case of a ! 1807: // PT class, it is the one that was supplied by the user ! 1808: if (!(class_name && ! 1809: (Pclass(class_name->tp)->class_base == ! 1810: instantiated_template_class) && nn->n_redefined)) ! 1811: { ! 1812: error("two definitions of%n",this); ! 1813: f->body = 0; ! 1814: } ! 1815: return 0; ! 1816: } ! 1817: ! 1818: if (f->body) goto bdbd; ! 1819: ! 1820: goto stst; ! 1821: } ! 1822: else if (nf->base != FCT) { ! 1823: error("%n declared both as%t and asF",this,nf); ! 1824: f->body = 0; ! 1825: } ! 1826: else { ! 1827: //error('d',"%t->check(%t) -> %d %d",nf,f,nf->check(f,OVERLOAD)/*,vrp_equiv*/); ! 1828: if (nf->check(f,OVERLOAD)/* || vrp_equiv */|| const_problem) { ! 1829: if (f->body && n_qualifier) { ! 1830: error("%nT mismatch: %t and %t",nn,nf,f); ! 1831: return 0; ! 1832: } ! 1833: Pgen g = new gen; ! 1834: add_first = 1; ! 1835: Pname n1 = g->add(nn); ! 1836: add_first = 0; ! 1837: string = nn->string; ! 1838: Pname n2 = g->add(this); ! 1839: nn->tp = g; ! 1840: nn = n2; ! 1841: goto thth; ! 1842: } ! 1843: ! 1844: if (in_class_dcl) { ! 1845: // error("twoDs of%n",this); ! 1846: // f->body = 0; ! 1847: // return 0; ! 1848: } ! 1849: else if (nf->f_static && f->f_inline==0 && n_sto==STATIC) { ! 1850: //error('d',"MF%n declared static outsideF",this); ! 1851: n_sto = 0; ! 1852: } ! 1853: else if (n_sto && n_sto!=nn->n_scope) { ! 1854: if (n_sto==EXTERN && nn->n_scope==STATIC) ! 1855: error('w',"%n declared extern after being declared static",this); ! 1856: else if (nf->f_inline==0 && f->f_inline==0) { ! 1857: extern Pname new_fct; // beware of pre-defined functions ! 1858: extern Pname del_fct; ! 1859: if (nn->tp==new_fct->tp || nn->tp==del_fct->tp) ! 1860: nn->n_sto = n_sto; ! 1861: else ! 1862: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:EXTERN); ! 1863: } ! 1864: } ! 1865: ! 1866: //error('d',"fct %n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope); ! 1867: ! 1868: extern linkage; ! 1869: //error('d',"link %d lcount %d sig %s",linkage,lcount,nf->f_signature); ! 1870: if (linkage && nf->f_signature && nf->f_signature[0]) ! 1871: error("inconsistent linkage specifications for%n",this); ! 1872: if (nf->body && f->body) { ! 1873: // Preserve the original definition in the case of a ! 1874: // PT class, it is the one that was supplied by the user ! 1875: if (!(class_name && ! 1876: (Pclass(class_name->tp)->class_base == ! 1877: instantiated_template_class) && nn->n_redefined)) ! 1878: { ! 1879: error("two definitions of%n",this); ! 1880: f->body = 0; ! 1881: } ! 1882: return 0; ! 1883: } ! 1884: ! 1885: if (f->body) goto bdbd; ! 1886: ! 1887: goto stst; ! 1888: ! 1889: bdbd: ! 1890: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf); ! 1891: f->f_virtual = nf->f_virtual; ! 1892: f->f_this = nf->f_this; ! 1893: f->f_result = nf->f_result; ! 1894: f->s_returns = nf->s_returns; ! 1895: f->f_args = nf->f_args; ! 1896: // f->argtype = nf->argtype; ! 1897: f->f_signature = nf->f_signature; ! 1898: f->f_const = nf->f_const; ! 1899: f->f_static = nf->f_static; ! 1900: nn->tp = f; ! 1901: if (f->f_inline) { ! 1902: if (nf->f_inline==0) { ! 1903: if (nn->n_used && nn->n_sto!=STATIC) ! 1904: error("%n declared with external linkage and called before defined as inline",nn); ! 1905: // else if (nf->memof) ! 1906: // error('w',"%n declared as non-inline but defined as inline",nn); ! 1907: else if (nn->n_used) { ! 1908: nn->take_addr(); // force printout ! 1909: if (warning_opt) error('w',"%n called before defined as inline",nn); ! 1910: } ! 1911: } ! 1912: nf->f_inline = 1; ! 1913: nn->n_sto = STATIC; ! 1914: } ! 1915: else if (nf->f_inline) { ! 1916: // error('w',"%n defined as inline but not declared as inline",this); ! 1917: f->f_inline = 1; ! 1918: } ! 1919: goto stst2; ! 1920: ! 1921: stst: ! 1922: //error('d',"stst"); ! 1923: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf); ! 1924: f->f_args = nf->f_args; ! 1925: // f->argtype = nf->argtype; ! 1926: stst2: ! 1927: //error('d',"stst2 %n printed %d",nn,nn->n_dcl_printed); ! 1928: if (f->f_inline) n_sto = STATIC; ! 1929: if (n_sto ! 1930: && nn->n_scope!=n_sto ! 1931: && friend_in_class==0 ! 1932: && f->f_inline==0){ // allow re-def to "static" ! 1933: if (n_sto == STATIC) ! 1934: nn->n_sto = STATIC; ! 1935: else { ! 1936: error("%n both%k and%k",this,n_sto,nn->n_scope); ! 1937: } ! 1938: } ! 1939: n_scope = nn->n_scope; // first specifier wins ! 1940: n_sto = nn->n_sto; ! 1941: } ! 1942: } ! 1943: else { // new function: make f_this for member functions ! 1944: thth: ! 1945: just_made = 1; ! 1946: if (f->f_inline) ! 1947: nn->n_sto = STATIC; ! 1948: else if (class_name==0 && n_sto==0 && f->body==0) ! 1949: nn->n_sto = EXTERN; ! 1950: //error('d',"thth %n %t static %d sto %k",nn,f,f->f_static,nn->n_sto); ! 1951: if (f->f_static) ! 1952: switch (n_oper) { // what about + ?? ! 1953: case CTOR: ! 1954: case DTOR: ! 1955: case TYPE: ! 1956: case CALL: ! 1957: case DEREF: ! 1958: case REF: ! 1959: error("%n cannot be a staticMF",nn); ! 1960: f->f_static = 0; ! 1961: } ! 1962: ! 1963: if (class_name ! 1964: && f->f_static==0 // no ``this'' in static members ! 1965: && n_oper!=NEW // X::operator new() static by default ! 1966: && n_oper!=DELETE // X::operator delete() static by default ! 1967: && etbl!=gtbl) { /* beware of implicit declatation */ ! 1968: Pname cn = nn->n_table->t_name; ! 1969: Pname tt = new name("this"); ! 1970: tt->n_scope = ARG; ! 1971: tt->where = no_where; ! 1972: // tt->n_sto = ARG; ! 1973: tt->tp = Pclass(class_name->tp)->this_type; ! 1974: PERM(tt); ! 1975: Pfct(nn->tp)->f_this = f->f_this = Pfct(nn->tp)->f_args = f->f_args = tt; ! 1976: tt->n_list = f->argtype; ! 1977: //error('d',"nn %n tp %t const %d",nn,nn->tp,f->f_const); ! 1978: if (f->f_const /*&& n_oper!=CTOR && n_oper!=DTOR*/) { ! 1979: Pbase x = Pbase(Pptr(tt->tp)->typ); ! 1980: Pbase y = new basetype(COBJ,0); ! 1981: *y = *x; ! 1982: y->b_const = 1; ! 1983: tt->tp = new ptr(PTR,y); ! 1984: PERM(tt->tp); ! 1985: } ! 1986: ! 1987: } ! 1988: else { ! 1989: Pfct(nn->tp)->f_args = f->f_args = f->f_result?f->f_result:f->argtype; ! 1990: Pfct(nn->tp)->f_signature = f->f_signature; ! 1991: Pfct(nn->tp)->f_const = f->f_const; ! 1992: Pfct(nn->tp)->f_static = f->f_static; ! 1993: } ! 1994: ! 1995: extern linkage; ! 1996: // if C++ linkage encode type in function name ! 1997: if (linkage==0 && Pfct(nn->tp)->f_signature==0) Pfct(nn->tp)->sign(); ! 1998: ! 1999: if (f->f_result == 0) { ! 2000: //error('d',"re1 %n %t %d",this,f,f); ! 2001: make_res(f); ! 2002: } ! 2003: else if (f->f_this) ! 2004: f->f_this->n_list = f->f_result; ! 2005: ! 2006: if (nn->n_oper==CTOR || nn->n_oper==DTOR) vbase_pointers(nn,Pclass(class_name->tp)); ! 2007: ! 2008: if (f->f_virtual) { ! 2009: switch (nn->n_scope) { ! 2010: default: ! 2011: error("nonC virtual%n",this); ! 2012: break; ! 2013: case 0: ! 2014: case PUBLIC: ! 2015: // if (fvirt) //BSopt ! 2016: cc->cot->virt_count = 1; ! 2017: Pfct(nn->tp)->f_virtual = f->f_virtual; ! 2018: break; ! 2019: } ! 2020: } ! 2021: } ! 2022: ! 2023: /* an operator must take at least one class object or ! 2024: reference to class object argument ! 2025: */ ! 2026: ! 2027: if (just_made) ! 2028: switch (n_oper) { ! 2029: case CTOR: ! 2030: switch (f->nargs) { // check for X(X) and X(X&) ! 2031: case 0: ! 2032: break; ! 2033: default: // handle X(X&, int i = 0) ! 2034: { Pname n2 = f->argtype->n_list; ! 2035: if (n2->n_initializer==0 && n2->n_evaluated==0) break; ! 2036: } ! 2037: case 1: ! 2038: { ! 2039: Ptype t = f->argtype->tp; ! 2040: clll: ! 2041: switch (t->base) { ! 2042: case TYPE: ! 2043: t = Pbase(t)->b_name->tp; ! 2044: goto clll; ! 2045: case RPTR: /* X(X&) ? */ ! 2046: t = Pptr(t)->typ; ! 2047: cxll: ! 2048: switch (t->base) { ! 2049: case TYPE: ! 2050: t = Pbase(t)->b_name->tp; ! 2051: goto cxll; ! 2052: case COBJ: ! 2053: if (class_name == Pbase(t)->b_name) ! 2054: Pclass(class_name->tp)->c_itor = nn; ! 2055: } ! 2056: break; ! 2057: case COBJ: /* X(X) ? */ ! 2058: if (class_name == Pbase(t)->b_name) { ! 2059: error("badK %s(%s) use %s(%s&)",class_name->string,class_name->string,class_name->string,class_name->string); ! 2060: f->argtype->tp = any_type; ! 2061: } ! 2062: } ! 2063: } ! 2064: } ! 2065: if (Pclass(class_name->tp)->c_ctor == 0) Pclass(class_name->tp)->c_ctor = nn; ! 2066: break; ! 2067: ! 2068: case TYPE: ! 2069: // somewhat simple minded solution to the inheritance of ! 2070: // conversion operator problem ! 2071: nn->n_list = Pclass(class_name->tp)->conv; ! 2072: Pclass(class_name->tp)->conv = nn; ! 2073: break; ! 2074: ! 2075: case DTOR: ! 2076: Pclass(class_name->tp)->c_dtor = nn; ! 2077: break; ! 2078: ! 2079: case NEW: // void* operator new(long) ! 2080: /* ! 2081: if (Pfct(nn->tp)->f_virtual) ! 2082: error("virtual%n (operator new() is static)",this); ! 2083: if (class_name) Pfct(nn->tp)->f_static = f->f_static = 1; // if member: static by default ! 2084: if (f->nargs_known != 1) ! 2085: error("ATs must be fully specified for%n",nn); ! 2086: else if (f->nargs<1) ! 2087: error("%n requires a firstA ofT size_t", nn); ! 2088: else if (f->argtype->tp->check(size_t_type,0)) { ! 2089: if (strict_opt==0 ! 2090: && f->argtype->tp->check(long_type,0)==0) { ! 2091: error('w',"%n firstA should be size_t",nn); ! 2092: f->argtype->tp = size_t_type; ! 2093: if (f->f_signature) Pfct(nn->tp)->sign(); ! 2094: } ! 2095: else ! 2096: error("%n requires a firstA ofT size_t",nn); ! 2097: } ! 2098: else { ! 2099: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 2100: if (t->check(Pvoid_type,0)) error("bad returnT for %n", nn); ! 2101: } ! 2102: break; ! 2103: */ ! 2104: case DELETE: // void operator delete(void*) or ! 2105: // void operator delete(void*, long) ! 2106: /* ! 2107: //error('d',"delete %n %t",nn,nn->tp); ! 2108: if (Pfct(nn->tp)->f_virtual) ! 2109: error("virtual%n (operator delete() is static)",this); ! 2110: if (class_name) Pfct(nn->tp)->f_static = f->f_static = 1; // if member: static by default ! 2111: if (f->nargs_known != 1) ! 2112: error("ATs must be fully specified for%n",nn); ! 2113: else { ! 2114: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 2115: if (t->base != VOID) ! 2116: error("bad returnT for %n", nn); ! 2117: else { ! 2118: switch (f->nargs) { ! 2119: default: ! 2120: error("%n takes 1 or 2As",nn); ! 2121: break; ! 2122: case 1: ! 2123: case 2: ! 2124: { Pname a = f->argtype; ! 2125: if (a->tp->check(Pvoid_type,0)) ! 2126: error("%n's 1stA must be a void*",nn); ! 2127: else if (a = a->n_list) { ! 2128: if (class_name == 0) ! 2129: error("%n takes only oneA",nn); ! 2130: else if (a->tp->check(size_t_type,0)) { ! 2131: if (strict_opt==0 ! 2132: && a->tp->check(long_type,0)==0) { ! 2133: error('w',"%n's 2ndA should be a size_t",nn); ! 2134: a->tp = size_t_type; ! 2135: if (f->f_signature) Pfct(nn->tp)->sign(); ! 2136: } ! 2137: else ! 2138: error("%n's 2ndA must be a size_t", nn); ! 2139: } ! 2140: } ! 2141: } ! 2142: } ! 2143: } ! 2144: } ! 2145: break; ! 2146: */ ! 2147: case CALL: ! 2148: case 0: ! 2149: break; ! 2150: ! 2151: default: ! 2152: if (f->nargs_known != 1) { ! 2153: error("ATs must be fully specified for%n",nn); ! 2154: } ! 2155: else if (class_name == 0) { ! 2156: Pname a; ! 2157: switch (f->nargs) { ! 2158: case 1: ! 2159: case 2: ! 2160: for (a=f->argtype; a; a=a->n_list) { ! 2161: Ptype tx = a->tp; ! 2162: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp; ! 2163: if (tx->is_ref()) tx = Pptr(tx)->typ; ! 2164: if (tx->is_cl_obj()) goto cok; ! 2165: } ! 2166: error("%n must take at least oneCTA",nn); ! 2167: break; ! 2168: default: ! 2169: error("%n must take 1 or 2As",nn); ! 2170: } ! 2171: } ! 2172: else { ! 2173: switch (f->nargs) { ! 2174: case 0: ! 2175: case 1: ! 2176: break; ! 2177: default: ! 2178: error("%n must take 0 or 1As",nn); ! 2179: } ! 2180: } ! 2181: cok:; ! 2182: } ! 2183: ! 2184: int i = 0; // check that every argument after an argument with ! 2185: // initializer have an initializer ! 2186: for (Pname a = f->f_args/*f->argtype*/; a; a=a->n_list) { ! 2187: if (a->n_initializer) ! 2188: i = 1; ! 2189: else if (i) ! 2190: error("trailingA%n withoutIr",a); ! 2191: } ! 2192: ! 2193: /* ! 2194: the body cannot be checked until the name ! 2195: has been checked and entered into its table ! 2196: */ ! 2197: if (f->body) f->dcl(nn); ! 2198: return nn; ! 2199: } ! 2200: /* ODI notes - ! 2201: template classes ! 2202: n_gen_fct_name -- this used to be an invalid pun on ! 2203: another field. ! 2204: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.