|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/dcl4.c 1.3.4.33" */ ! 2: /************************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All rigths Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: dcl4.c: ! 11: Declaration of class and enum ! 12: ! 13: *************************************************************************/ ! 14: ! 15: #include "cfront.h" ! 16: #include "size.h" ! 17: ! 18: extern loc no_where; ! 19: ! 20: Pname find_vptr(Pclass); ! 21: void fix_args(Pfct f, Pclass cl) ! 22: /* ! 23: This function is used to cope with the case where cl::cl(cl&) is ! 24: declared AFTER f has been declared ! 25: set n_xref bit for f ! 26: */ ! 27: { ! 28: for (Pname a = f->argtype; a; a = a->n_list) { ! 29: Pname n = a->tp->is_cl_obj(); ! 30: if (n && Pclass(n->tp)==cl) a->n_xref = 1; ! 31: } ! 32: } ! 33: ! 34: Pname merge_conv(Pname c1, Pname c2) ! 35: { ! 36: if (c1 == 0) return c2; ! 37: if (c2 == 0) return c1; ! 38: if (c1 == c2) return c1; ! 39: error('s',"cannot merge lists of conversion functions"); ! 40: return c1; ! 41: } ! 42: ! 43: static Eppp; ! 44: ! 45: char* get_classname(char* s) ! 46: /* ! 47: retrieve the outermost class name in a vtable name ! 48: */ ! 49: { ! 50: //error('d',"get_classname(%s)",s); ! 51: char* s1 = 0; ! 52: ! 53: while (*s) { ! 54: s1 = s; ! 55: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++); ! 56: if (*s) s += 2; // bypass "__" ! 57: } ! 58: ! 59: return s1; ! 60: } ! 61: ! 62: char* drop_classname(char* s) ! 63: /* ! 64: retrieve all but the outermost class name in a vtable name ! 65: */ ! 66: { ! 67: //error('d',"drop_classname(%s)",s); ! 68: char* r = new char[strlen(s)+1]; ! 69: sprintf(r,s); ! 70: s = r; ! 71: ! 72: char* s1 = s; ! 73: while (*s) { ! 74: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++); ! 75: if (*s) { ! 76: s1 = s; ! 77: s += 2; // bypass "__" ! 78: } ! 79: } ! 80: ! 81: *s1 = '\0'; ! 82: ! 83: return (*r) ? r : 0; ! 84: } ! 85: ! 86: Pbcl classdef::get_base( char *s ) ! 87: /* ! 88: Find the base class whose name matches the argument ! 89: */ ! 90: { ! 91: //error('d',"%t::get_base(%s)",this,s); ! 92: for (Pbcl b = baselist; b; b = b->next) { ! 93: for ( char *s1 = s, *s2 = b->bclass->string; ! 94: *s1 && *s2 && *s1 == *s2; ! 95: s1++, s2++); ! 96: ! 97: if (!(*s1 || *s2)) ! 98: break; ! 99: } ! 100: ! 101: return b; ! 102: } ! 103: ! 104: int classdef::get_offset(char* s) ! 105: /* ! 106: Get offset represented by string as viewed from "this" ! 107: */ ! 108: { ! 109: //error('d',"%t::get_offset(%s)",this,s); ! 110: if (!s) return 0; ! 111: ! 112: Pbcl b = get_base(get_classname(s)); ! 113: ! 114: return b->obj_offset + b->bclass->get_offset(drop_classname(s)); ! 115: } ! 116: ! 117: char* vtbl_str(char* s1, char* s2) ! 118: /* ! 119: combine two pieces of a vtbl name ! 120: */ ! 121: { ! 122: //error('d',"vtbl_str(%s,%s)",s1,s2); ! 123: char* s3; ! 124: if (s1) ! 125: if (s2) { ! 126: s3 = new char[strlen(s1)+strlen(s2)+3]; ! 127: sprintf(s3,"%s__%s",s1,s2); ! 128: return s3; ! 129: } ! 130: else ! 131: return s1; ! 132: else ! 133: return s2; ! 134: } ! 135: ! 136: void classdef::add_vtbl(velem* v, char* s, bit virt_flag) ! 137: /* ! 138: add vtbl to virt_list ! 139: */ ! 140: { ! 141: //error('d',"%t->add_vtbl(%d,%s)",this,v,s); ! 142: Pvirt vtab = new virt(this, v, s, virt_flag); ! 143: ! 144: if (virt_flag) has_vvtab = 1; ! 145: ! 146: if (!virt_list) { ! 147: virt_list = vtab; ! 148: return; ! 149: } ! 150: ! 151: // If conficting vtable entries are made because of ! 152: // a virtual base class, must be considered an error. ! 153: for (Pvirt vt = virt_list; vt; vt = vt->next ) ! 154: // if (strcmp(vt->string,s)==0) { ! 155: if (vt->string && strcmp(vt->string,s)==0) { ! 156: velem* ivec = vt->virt_init; ! 157: Pname on = ivec[0].n; ! 158: Pname nn = v[0].n; ! 159: Pclass ocl,ncl; ! 160: for (int i=0; on && nn; i++,on=ivec[i].n,nn=v[i].n) { ! 161: ocl = Pfct(on->tp)->memof; ! 162: ncl = Pfct(nn->tp)->memof; ! 163: if (on != nn) ! 164: if (!ocl->has_base(ncl)) ! 165: if (!ncl->has_base(ocl)) ! 166: break; ! 167: else { ! 168: ivec[i].n = nn; ! 169: ivec[i].offset = v[i].offset; ! 170: } ! 171: } ! 172: if (on || nn) ! 173: error("virtualB: ambiguous%n and%n", on, nn); ! 174: return; ! 175: } ! 176: ! 177: vtab->next = virt_list->next; ! 178: virt_list->next = vtab; ! 179: } ! 180: ! 181: static int Voffset; // cope with offsets of virtuals in deep nests ! 182: extern TOK Nvirt; ! 183: int vcounter; ! 184: static vmax; ! 185: const vpChunk = 32; ! 186: ! 187: int classdef::do_virtuals(Pvirt vtab, char* str, int leftmost, bit virt_flag) ! 188: /* ! 189: make vtbl for b in "this" ! 190: match up virtuals and assign virtual indices for the base or delegate "bcl" ! 191: first base class shares ``this'' and vtbl with this class ! 192: */ ! 193: { ! 194: if (vmax<vcounter) vmax = vcounter; ! 195: int vpsz = (vmax+vcounter)/vpChunk+1; // fragmentation prevention ! 196: vpsz *= vpChunk; ! 197: Pname* vp = new Pname[vpsz]; ! 198: velem* ivec = vtab ? vtab->virt_init : 0; ! 199: int vo = Voffset; ! 200: int vc = 0; ! 201: int changed = 0; ! 202: ! 203: //error('d',"%t->do_virtuals(%d,%s) voffset %d",this,vtab,str,Voffset); ! 204: //error('d',"virt_count %d vpsz %d vcounter %d",virt_count,vpsz,vcounter); ! 205: if (ivec) { // vtbl replacement for ivec ! 206: ! 207: extern vhack; ! 208: Pname vfct(Pclass,char*); ! 209: if (vtab->is_vbase) { ! 210: str = 0; ! 211: Voffset = get_offset(vtab->string); ! 212: } ! 213: else ! 214: Voffset = Voffset + vtab->vclass->get_offset(vtab->string); ! 215: Pname vn; ! 216: for (int i=0; vn=ivec[i].n; i++) { ! 217: ! 218: /* go through virtual table's list of virtuals: ! 219: first see if the function is simply inherited ! 220: if not, check for a match ! 221: if not, then add as new ! 222: */ ! 223: // Pname vn = ivec[i]; ! 224: if ( i >= vpsz ) { // resize vp vector ! 225: int tvpsz = vpsz + vpChunk; ! 226: Pname *tvp = new Pname[ tvpsz ]; ! 227: for ( int j = 0; j < i; ++j ) ! 228: tvp[ j ] = vp[ j ]; ! 229: delete [vpsz] vp; ! 230: vp = tvp; ! 231: //error( 'd',"resizing: i: %d vpsz: %d tvpsz: %d", i, vpsz, tvpsz ); ! 232: vpsz = tvpsz; ! 233: } ! 234: ! 235: char* s = Pchar(vn->n_tbl_list); ! 236: Pname n = memtbl->look(s?s:vn->string, 0); ! 237: //error('d',"vn %n %s n %n %d",vn,s,n,Voffset); ! 238: if (n == 0) { // FCT + FCT ! 239: inher: // inherit ! 240: if (vn->n_initializer) error("cannot inherit pure virtualF%n",vn); ! 241: vp[i] = vn; ! 242: if ( ivec[i].offset && vtab->is_vbase ) ! 243: vp[i]->n_offset = Voffset - vo; ! 244: else ! 245: vp[i]->n_offset = ivec[i].offset; ! 246: continue; ! 247: } ! 248: ! 249: Pfct f = Pfct(n->tp); ! 250: // error ('d', "f %d", f ); ! 251: if (f == 0 ) continue; ! 252: //error('d',"f %t %d",f,f->f_virtual); ! 253: ! 254: if (s && f->base==OVERLOAD) { // OVERLOAD + OVERLOAD ! 255: // vn is overloaded and s is its name ! 256: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) ! 257: if (gl->f == vn) goto inher; ! 258: } ! 259: ! 260: extern Vcheckerror; ! 261: Pfct vnf = Pfct(vn->tp); ! 262: // re-define? ! 263: switch (f->base) { ! 264: default: ! 265: error('w',&n->where,"%n hides virtual%n",n,vn); ! 266: break; ! 267: case FCT: // derived::FCT ! 268: { ! 269: vhack = 1; ! 270: if (vnf->check(f,VIRTUAL) == 0) { // derived::FCT match base::FCT ! 271: //error('d',"vnf1 %t f %t vcheck %d",vnf,f,Vcheckerror); ! 272: // VTOK: virtual, but no index assigned ! 273: // you can only inherit an index from your first base ! 274: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 275: if (f->f_virtual==VTOK) f->f_virtual = i+1; ! 276: vp[i] = n; ! 277: vp[i]->n_offset = Voffset; ! 278: changed = 1; ! 279: } ! 280: else { ! 281: //error('d',"vnf2 %t f %t vcheck %d",vnf,f,Vcheckerror); ! 282: if (Vcheckerror) ! 283: error("bad virtualT match for %n",vn); ! 284: else ! 285: switch (f->f_virtual) { ! 286: case 0: ! 287: case VTOK: ! 288: error('w',&n->where,"%n hides virtual%n",n,vn); ! 289: } ! 290: vp[i] = vn; // not a new overloaded: inherit ! 291: if ( ivec[i].offset && vtab->is_vbase ) ! 292: vp[i]->n_offset = Voffset - vo; ! 293: else ! 294: vp[i]->n_offset = ivec[i].offset; ! 295: } ! 296: vhack = 0; ! 297: break; ! 298: } ! 299: case OVERLOAD: // derived::OVERLOAD ! 300: { ! 301: vhack = 1; ! 302: int hit = 0; ! 303: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) { ! 304: // try each fct from derived class ! 305: Pname fn = gl->f; ! 306: Pfct f = Pfct(fn->tp); ! 307: ! 308: if (f->check(vnf,VIRTUAL) == 0) { // derived::FCT ! 309: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 310: if (f->f_virtual==VTOK) f->f_virtual = i+1; ! 311: vp[i] = fn; ! 312: vp[i]->n_offset = Voffset; ! 313: changed = 1; ! 314: goto found; ! 315: } ! 316: else { ! 317: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 318: } ! 319: if (Vcheckerror == 0) ! 320: switch (f->f_virtual) { ! 321: case 0: ! 322: case VTOK: ! 323: hit = 1; ! 324: } ! 325: ! 326: } ! 327: ! 328: if (hit) error('w',&n->where,"%n hides virtual%n ofT %t",n,vn,vn->tp); ! 329: ! 330: vp[i] = vn; // not a new overloaded: inherit ! 331: if ( ivec[i].offset && vtab->is_vbase ) ! 332: vp[i]->n_offset = Voffset - vo; ! 333: else ! 334: vp[i]->n_offset = ivec[i].offset; ! 335: found: ! 336: vhack = 0; ! 337: break; ! 338: } ! 339: } ! 340: } ! 341: ! 342: Voffset = vo; ! 343: vc = i; ! 344: } ! 345: ! 346: //error( 'd', "out of loop: vc: %d vpsz: %d", vc, vpsz ); ! 347: ! 348: if (leftmost) { ! 349: /* ! 350: add new virtuals: ! 351: `VTOK' marks ``new virtual, no index assigned''. ! 352: You can only be new once (no base or first base). ! 353: */ ! 354: int i; ! 355: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { ! 356: Pfct f = Pfct(nn->tp); ! 357: ! 358: if ( vc >= vpsz ) { // resize vp vector ! 359: int tvpsz = vpsz + vpChunk; ! 360: Pname *tvp = new Pname[ tvpsz ]; ! 361: for ( int j = 0; j < vc; ++j ) ! 362: tvp[ j ] = vp[ j ]; ! 363: delete [vpsz] vp; ! 364: vp = tvp; ! 365: //error( 'd',"resizing2: vc: %d vpsz: %d tvpsz: %d", vc, vpsz, tvpsz ); ! 366: vpsz = tvpsz; ! 367: } ! 368: ! 369: //error('d',"f %n %t",nn,f); ! 370: if (f) ! 371: switch (f->base) { ! 372: case FCT: ! 373: //error('d',"fv %d",f->f_virtual); ! 374: if (f->f_virtual == VTOK) { ! 375: // declared virtual, or ! 376: // virtual in some base ! 377: f->f_virtual = ++vc; ! 378: vp[f->f_virtual-1] = nn; ! 379: vp[f->f_virtual-1]->n_offset = 0; ! 380: f->f_vdef = 1; ! 381: changed = 2; ! 382: } ! 383: break; ! 384: case OVERLOAD: ! 385: { for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) { ! 386: Pname fn = gl->f; ! 387: Pfct f = Pfct(fn->tp); ! 388: if (f->f_virtual == VTOK) { ! 389: f->f_virtual = ++vc; ! 390: vp[f->f_virtual-1] = fn; ! 391: vp[f->f_virtual-1]->n_offset = 0; ! 392: f->f_vdef = 1; ! 393: changed = 2; ! 394: } ! 395: } ! 396: break; ! 397: } ! 398: } ! 399: } ! 400: //error('d',"%s changed %d has_vvtab %d",string,changed,has_vvtab); ! 401: //error('d',"vc %d vpsz %d",vc,vpsz); ! 402: virt_count = 0; ! 403: if (changed) ! 404: virt_count = vc; ! 405: else if (has_vvtab) { ! 406: virt_merge = 1; ! 407: if (vc && vtab->is_vbase) ! 408: leftmost = 0; ! 409: } ! 410: } ! 411: ! 412: //error('d',"vc %d ch %d vp[%d] virt_count %d",vc,changed,vpsz,virt_count); ! 413: if (changed || !leftmost) { ! 414: // vc==0 if all explicit virtuals in fact were declared in base ! 415: velem* v = new velem[vc+1]; ! 416: ! 417: for (int i=0; i<vc; i++) { ! 418: v[i].n = vp[i]; ! 419: v[i].offset = vp[i]->n_offset; ! 420: } ! 421: v[vc].n = 0; ! 422: ! 423: if (leftmost) ! 424: add_vtbl(v,0,0); ! 425: else ! 426: add_vtbl(v,vtbl_str(vtab->string,str),virt_flag||vtab->is_vbase); ! 427: delete vp; ! 428: vcounter = 0; ! 429: return 1; ! 430: } ! 431: ! 432: delete vp; ! 433: vcounter = 0; ! 434: return 0; ! 435: } ! 436: ! 437: int classdef::all_virt(Pclass bcl, char* s, int leftmost, bit virt_flag) ! 438: { ! 439: //error('d',"%t::all_virt(%t,%s,%d)",this,bcl,s,leftmost); ! 440: int i = 0; ! 441: ! 442: if (bcl->virt_count) ! 443: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) { ! 444: // if (has_base(blist->vclass)) ! 445: // if (blist->vclass==bcl ! 446: // // bcl is virtual in both ! 447: // || ((Nvirt=0,blist->vclass->has_base(bcl)) && Nvirt==VIRTUAL ! 448: // && (Nvirt=0,has_base(bcl)) && Nvirt==VIRTUAL ! 449: // ) ! 450: // ) ! 451: if (virt_merge && !(virt_flag || blist->is_vbase)) ! 452: continue; ! 453: ! 454: i += do_virtuals(blist, s, leftmost, virt_flag); ! 455: if (!i && leftmost && !virt_merge) ! 456: return 0; ! 457: ! 458: leftmost = 0; ! 459: } ! 460: ! 461: // finding virt_list stops recursive step ! 462: // if vtables found and updated, return number ! 463: if (i) return i; ! 464: ! 465: for (Pbcl b = bcl->baselist; b; b = b->next) { ! 466: // if (b->base==PTR) continue; ! 467: if (b->promoted) continue; ! 468: //error('d',"b %t vl %d bl %d",b->bclass,b->bclass->virt_list,b->bclass->baselist); ! 469: if (leftmost && b->base == VIRTUAL) { ! 470: i += do_virtuals(0, 0, 1, 0); ! 471: if (!i && !virt_merge) ! 472: return 0; ! 473: leftmost = 0; ! 474: } ! 475: int vo = Voffset; ! 476: Voffset += b->obj_offset; ! 477: //error('d',"offset %t %d",b->bclass,Voffset); ! 478: ! 479: if (b->base==VIRTUAL) ! 480: i += all_virt(b->bclass, b->bclass->string, leftmost, 1); ! 481: else ! 482: i += all_virt(b->bclass, vtbl_str(b->bclass->string,s), leftmost, virt_flag); ! 483: if (!i && leftmost && !virt_merge) ! 484: return 0; ! 485: ! 486: Voffset = vo; ! 487: leftmost = 0; ! 488: } ! 489: ! 490: // if recursion updated vtables, return number ! 491: if (i) return i; ! 492: ! 493: // no vtables updated in recursion ! 494: // look for new virtuals ! 495: if (leftmost) ! 496: return do_virtuals(0, 0, 1, 0); ! 497: else ! 498: return 0; ! 499: } ! 500: ! 501: Pexpr copy_obj(Pexpr l, Pexpr r, int sz) ! 502: /* ! 503: generate: ! 504: struct _s { char[sz]; }; ! 505: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 506: */ ! 507: { ! 508: if ( !sz ) sz = 1; ! 509: //error('d',"copy(%d)",sz); ! 510: char* s = make_name('S'); ! 511: fprintf(out_file,"struct %s { char v[%d]; };\n",s,sz); ! 512: Pname n = new name(s); ! 513: Ptype t = new basetype(COBJ,n); ! 514: t = new ptr(PTR,t); ! 515: ! 516: l = new texpr(CAST,t,l);//new cast(t,l); ! 517: l = l->contents(); ! 518: ! 519: r = new texpr(CAST,t,r);//new cast(t,r); ! 520: r = r->contents(); ! 521: ! 522: return new expr(ASSIGN,l,r); ! 523: } ! 524: /* ! 525: Pname make_default_ctor(Pclass cl) ! 526: { ! 527: //error('d',"make_ctor %t",cl); ! 528: Pname cn = ktbl->look(cl->string,0); ! 529: if (cn) cn = Pbase(cn->tp)->b_name; ! 530: cc->stack(); ! 531: cc->not = cn; ! 532: cc->cot = cl; ! 533: Pname fn = new name(cl->string); ! 534: Pfct f = new fct(defa_type,0,1); ! 535: fn->tp = f; ! 536: fn->n_oper = TNAME; ! 537: // fn->n_sto = STATIC; ! 538: ! 539: Pfct(f)->f_inline = 1; ! 540: f->body = new block(curloc,0,0); ! 541: ! 542: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 543: delete fn; ! 544: ! 545: cc->unstack(); ! 546: nn->simpl(); ! 547: if (debug_opt) nn->dcl_print(0); ! 548: //error('d',"make_ctor->"); ! 549: return nn; ! 550: } ! 551: ! 552: Pname make_default_dtor(Pclass cl) ! 553: { ! 554: //error('d',"make_dtor %t",cl); ! 555: Pname cn = ktbl->look(cl->string,0); ! 556: if (cn) cn = Pbase(cn->tp)->b_name; ! 557: cc->stack(); ! 558: cc->not = cn; ! 559: cc->cot = cl; ! 560: Pname fn = new name(cl->string); ! 561: Pfct f = new fct(defa_type,0,1); ! 562: fn->tp = f; ! 563: fn->n_oper = DTOR; ! 564: // fn->n_sto = STATIC; ! 565: ! 566: Pfct(f)->f_inline = 1; ! 567: f->body = new block(curloc,0,0); ! 568: ! 569: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 570: delete fn; ! 571: ! 572: cc->unstack(); ! 573: nn->simpl(); ! 574: if (debug_opt) nn->dcl_print(0); ! 575: //error('d',"make_dtor->"); ! 576: return nn; ! 577: } ! 578: */ ! 579: ! 580: Ptype find_arg_type(Pclass cl) ! 581: // first determine argument type ! 582: { ! 583: int i; ! 584: int mod = 0; ! 585: for (Pbcl b = cl->baselist; b; b = b->next) { ! 586: Pclass bcl = b->bclass; ! 587: switch (b->base) { ! 588: case VIRTUAL: ! 589: case NAME: // generate :b(*(b*)&arg) ! 590: { ! 591: Pname itor = bcl->has_itor(); ! 592: if (itor && itor->tp->base==FCT) { ! 593: Pname a = Pfct(itor->tp)->argtype; ! 594: Pptr p = a->tp->is_ref(); ! 595: if (p && p->typ->tconst()==0) { ! 596: mod = 1; ! 597: goto ll1; ! 598: } ! 599: } ! 600: } ! 601: } ! 602: } ! 603: ll1: ! 604: if (mod == 0) ! 605: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) { ! 606: Pname cln; ! 607: // ignore static members ! 608: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 609: ! 610: if (cln = m->tp->is_cl_obj()) { ! 611: Pname itor = Pclass(cln->tp)->has_itor(); ! 612: if (itor && itor->tp->base==FCT) { ! 613: Pname a = Pfct(itor->tp)->argtype; ! 614: Pptr p = a->tp->is_ref(); ! 615: if (p && p->typ->tconst()==0) { ! 616: mod = 1; ! 617: goto ll2; ! 618: } ! 619: } ! 620: } ! 621: } ! 622: ll2: ! 623: //error('d',"mod %d",mod); ! 624: Pbase bp = new basetype(INT,0); ! 625: *bp = *Pbase(Pptr(cl->this_type)->typ); ! 626: if (mod == 0) bp->b_const = 1; ! 627: return new ptr(RPTR,bp); ! 628: } ! 629: ! 630: Pname classdef::make_itor(int def) ! 631: /* ! 632: make cn::cn(const cn&) :bases_and_members_of_cn {} ! 633: */ ! 634: { ! 635: //error('d',"%t->make_itor(%d) %d",this,def,obj_size); ! 636: Pstmt s; ! 637: Pname e; ! 638: int i; ! 639: Pname arg = new name(make_name('A')); ! 640: /* ! 641: int mod = 0; // first determine argument type ! 642: { ! 643: for (Pbcl b = baselist; b; b = b->next) { ! 644: Pclass bcl = b->bclass; ! 645: switch (b->base) { ! 646: case VIRTUAL: ! 647: case NAME: // generate :b(*(b*)&arg) ! 648: { ! 649: Pname itor = bcl->has_itor(); ! 650: if (itor && itor->tp->base==FCT) { ! 651: Pname a = Pfct(itor->tp)->argtype; ! 652: Pptr p = a->tp->is_ref(); ! 653: if (p && p->typ->tconst()==0) { ! 654: mod = 1; ! 655: goto ll1; ! 656: } ! 657: } ! 658: } ! 659: } ! 660: } ! 661: ll1: ! 662: if (mod == 0) ! 663: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 664: Pname cln; ! 665: // ignore static members ! 666: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 667: ! 668: if (cln = m->tp->is_cl_obj()) { ! 669: Pname itor = Pclass(cln->tp)->has_itor(); ! 670: if (itor && itor->tp->base==FCT) { ! 671: Pname a = Pfct(itor->tp)->argtype; ! 672: Pptr p = a->tp->is_ref(); ! 673: if (p && p->typ->tconst()==0) { ! 674: mod = 1; ! 675: goto ll2; ! 676: } ! 677: } ! 678: } ! 679: } ! 680: ll2: ! 681: //error('d',"mod %d",mod); ! 682: Pbase bp = new basetype(INT,0); ! 683: *bp = *Pbase(Pptr(this_type)->typ); ! 684: if (mod == 0) bp->b_const = 1; ! 685: arg->tp = new ptr(RPTR,bp); ! 686: } ! 687: */ ! 688: arg->tp = find_arg_type(this); ! 689: ! 690: // c_xref = 2; // now it has X(X&) ! 691: c_xref |= C_XREF; // now it has X(X&) ! 692: ! 693: if (def) { ! 694: // define itor ! 695: int slow = 0; // slow==0 => copy using vector copy ! 696: int first = 1; ! 697: Pexpr es = 0; ! 698: s = new estmt(SM,no_where,0,0); ! 699: e = 0; ! 700: ! 701: ! 702: if (warning_opt && 128<obj_size) ! 703: error('w',"copying a %d byte object (ofC%n)",obj_size,this); ! 704: ! 705: if (baselist) slow = 1; ! 706: ! 707: //for (Pbcl v = baselist; v; v = v->next) ! 708: // if (v->base == VIRTUAL) { ! 709: // slow = 1; ! 710: // break; ! 711: // } ! 712: ! 713: // initialize bases: ! 714: if (slow) ! 715: for (Pbcl b = baselist; b; b = b->next) { ! 716: Pclass bcl = b->bclass; ! 717: Ptype pt = bcl->this_type; ! 718: //error('d',"base %t %k offset %d ptroffset %d",bcl,b->base,b->obj_offset,b->ptr_offset); ! 719: switch (b->base) { ! 720: case VIRTUAL: ! 721: case NAME: // generate :b(*(b*)&arg) ! 722: { ! 723: Pexpr b2 = new name(arg->string); ! 724: b2 = b2->address(); ! 725: b2 = new texpr(CAST,pt,b2);//new cast(pt,b2); ! 726: b2->i2 = 1; ! 727: b2 = b2->contents(); ! 728: ! 729: Pname ee = new name(bcl->string); ! 730: ee->base = TNAME; ! 731: ee->n_initializer = b2; ! 732: if (e) ee->n_list = e; ! 733: e = ee; ! 734: break; ! 735: } ! 736: } ! 737: } ! 738: ! 739: // initialize members ! 740: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 741: // ignore static members ! 742: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 743: ! 744: /*AAA // can copy vptr, X(X&) sets it anyway ! 745: if (strcmp(m->string,"__vptr")==0) { ! 746: //error('d',"%t vptr: %d",this,first); ! 747: if (first==0 && m->n_offset) { ! 748: Pexpr th = new expr(THIS,0,0); ! 749: Pexpr a = new name(arg->string); ! 750: a = a->address(); ! 751: Pexpr ee = copy_obj(th,a,m->n_offset); ! 752: es = es ? new expr(CM,es,ee) : ee; ! 753: } ! 754: slow = 1; ! 755: first = 0; ! 756: continue; ! 757: } ! 758: AAA*/ ! 759: Ptype mt = m->tp; ! 760: tx: ! 761: switch (mt->base) { ! 762: case TYPE: ! 763: mt = Pbase(mt)->b_name->tp; ! 764: goto tx; ! 765: case VEC: ! 766: { Pname cn = Pvec(mt)->typ->is_cl_obj(); ! 767: //error('d',"vec %n %t xref %d",m,mt,cn?Pclass(cn->tp)->c_xref:0); ! 768: if (cn && Pclass(cn->tp)->c_xref&(C_XREF|C_VBASE)) { ! 769: error('s',"copy of %n[], no memberwise copy for%n",cn,cn); ! 770: slow = 1; // make sure an assignment operator ! 771: // is generated so that there will ! 772: // be no more error messages ! 773: } ! 774: ! 775: if (slow && mt->tsizeof()) { ! 776: /* ! 777: generate: ! 778: struct _s { char[sizeof(m)]; }; ! 779: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 780: */ ! 781: Pexpr l = new name(m->string); ! 782: Pexpr r = new name(m->string); ! 783: r = new ref(DOT,new name(arg->string),r); ! 784: Pexpr ee = copy_obj(l,r,mt->tsizeof()); ! 785: es = es ? new expr(CM,es,ee) : ee; ! 786: break; ! 787: } ! 788: } ! 789: case FCT: ! 790: case OVERLOAD: ! 791: case CLASS: ! 792: case ENUM: ! 793: break; ! 794: case COBJ: ! 795: { Pclass mcl = Pclass(Pbase(mt)->b_name->tp); ! 796: if (slow==0 // if slow, previous members have ! 797: // already been copied ! 798: && mcl->c_xref&(C_VBASE|C_XREF)) { ! 799: slow = 1; ! 800: if (first==0 && m->n_offset) { ! 801: //AAA copy up to here ! 802: Pexpr th = new expr(THIS,0,0); ! 803: Pexpr a = new name(arg->string); ! 804: a = a->address(); ! 805: Pexpr ee = copy_obj(th,a,m->n_offset); ! 806: es = es ? new expr(CM,es,ee) : ee; ! 807: } ! 808: } ! 809: // no break ! 810: } ! 811: ! 812: default: ! 813: if (slow) { ! 814: //error('d',"slow %s %s",m->string,arg->string); ! 815: Pname ee = new name(m->string); ! 816: ee->n_initializer = new ref(DOT,new name(arg->string),new name(m->string)); ! 817: if (e) ee->n_list = e; ! 818: e = ee; ! 819: } ! 820: } ! 821: first = 0; ! 822: } ! 823: ! 824: if (slow == 0) { ! 825: /* really simple just copy: ! 826: the only problem was a vptr which can be ! 827: ignored since X(X&) is going to reset it anyway ! 828: don't use assignment of this struct to avoid operator= ! 829: */ ! 830: Pexpr th = new expr(THIS,0,0); ! 831: Pexpr a = new name(arg->string); ! 832: a = a->address(); ! 833: Pexpr ee = copy_obj(th,a,obj_size); ! 834: es = es ? new expr(CM,es,ee) : ee; ! 835: } ! 836: ! 837: s->e = es; ! 838: Pname cn = ktbl->look(string,0); ! 839: if (cn) cn = Pbase(cn->tp)->b_name; ! 840: cc->stack(); ! 841: cc->not = cn; ! 842: cc->cot = this; ! 843: } ! 844: Pname fn = new name(string); ! 845: Pfct f = new fct(defa_type,arg,1); ! 846: fn->tp = f; ! 847: fn->n_oper = TNAME; ! 848: // fn->n_sto = STATIC; ! 849: ! 850: Pfct(f)->f_inline = def?1:ITOR; // ITOR means ``define itor() if used'' ! 851: if (def) { ! 852: f->body = new block(curloc,0,s); ! 853: f->f_init = e; ! 854: } ! 855: ! 856: Pname nn = fn->dcl(memtbl,PUBLIC); ! 857: delete fn; ! 858: ! 859: if (def) { ! 860: cc->unstack(); ! 861: nn->simpl(); ! 862: if (debug_opt) nn->dcl_print(0); ! 863: } ! 864: //error('d',"make_itor->"); ! 865: return nn; ! 866: } ! 867: ! 868: int make_assignment(Pname cn) ! 869: /* ! 870: write the function: ! 871: ! 872: X& X::operator=(const X&) { assign all bases and members } ! 873: ! 874: return 1 is a function is really synthesized ! 875: */ ! 876: { ! 877: Pclass cl = Pclass(cn->tp); ! 878: Pstmt s = new estmt(SM,no_where,0,0); ! 879: Pexpr e = 0; ! 880: Pname arg = new name(make_name('A')); ! 881: basetype* bp = new basetype(INT,0); ! 882: *bp = *Pbase(Pptr(cl->this_type)->typ); ! 883: bp->b_const = 1; ! 884: // arg->tp = new ptr(RPTR,bp); ! 885: arg->tp = find_arg_type(cl); ! 886: //error('d',"make_assignment %t %d",cl,cl->obj_size); ! 887: // cl->c_xref |= 4; // now it has X::operator=(const X&) ! 888: ! 889: if (warning_opt && 128<cl->obj_size) ! 890: error('w',"copying a %d byte object (ofC%n)",cl->obj_size,cl); ! 891: { ! 892: int slow = 0; // slow==0 => copy using vector copy ! 893: int first = 1; // first==1 => first member of (derived) class ! 894: ! 895: if (cl->baselist) slow = 1; // be dumb and safe ! 896: // for (Pbcl v = cl->baselist; v; v = v->next) ! 897: // if (v->base==VIRTUAL || v->c_xref&(C_VBASE|C_ASS)) { ! 898: // slow = 1; ! 899: // break; ! 900: // } ! 901: ! 902: if (slow) ! 903: for (Pbcl b = cl->baselist; b; b = b->next) { ! 904: Pclass bcl = b->bclass; ! 905: Ptype pt = bcl->this_type; ! 906: switch (b->base) { ! 907: case NAME: ! 908: { // generate: *(bcl*)this = *(bcl*)&arg; ! 909: //error('d',"base %t",bcl); ! 910: Pexpr b1 = new expr(THIS,0,0); ! 911: b1 = new texpr(CAST,pt,b1); ! 912: b1 = b1->contents(); ! 913: ! 914: Pexpr b2 = new name(arg->string); ! 915: b2 = b2->address(); ! 916: b2 = new texpr(CAST,pt,b2); ! 917: b2->i2 = 1; ! 918: b2 = b2->contents(); ! 919: ! 920: Pexpr ee = new expr(ASSIGN,b1,b2); ! 921: e = e ? new expr(CM,e,ee) : ee; ! 922: break; ! 923: } ! 924: case VIRTUAL: ! 925: if (warning_opt) ! 926: error('w',"copying an object ofC%n with s virtualBC",cl); ! 927: if (b->ptr_offset) { ! 928: // copy object, but not pointer ! 929: // generate: *(bcl*)this->Pw = *(bcl*)arg->Pw; ! 930: ! 931: // I don't know how to avoid copying the object ! 932: // once for each pointer ! 933: ! 934: Pexpr b1 = new expr(THIS,0,0); ! 935: b1 = new mdot(bcl->string,b1); ! 936: b1->i1 = 3; ! 937: b1->tp = pt; ! 938: b1 = new expr(DEREF,b1,0);//b1->contents(); ! 939: ! 940: Pexpr b2 = new name(arg->string); ! 941: b2 = b2->address(); ! 942: b2 = new mdot(bcl->string,b2); ! 943: b2->i1 = 3; ! 944: b2->tp = pt; ! 945: b2 = new expr(DEREF,b2,0);//b2->contents(); ! 946: ! 947: Pexpr ee = new expr(ASSIGN,b1,b2); ! 948: e = e ? new expr(CM,e,ee) : ee; ! 949: } ! 950: break; ! 951: } ! 952: } ! 953: ! 954: int i; ! 955: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) { ! 956: // ignore static members ! 957: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 958: ! 959: if (strcmp(m->string,"__vptr")==0) { // don't copy vptrs ! 960: // we may be copying ! 961: // into a base class object ! 962: if (first==0 && m->n_offset) { ! 963: // copy up to (but not including) vptr ! 964: // don't copy if first member ! 965: Pexpr th = new expr(THIS,0,0); ! 966: Pexpr a = new name(arg->string); ! 967: a = a->address(); ! 968: Pexpr ee = copy_obj(th,a,m->n_offset); ! 969: e = e ? new expr(CM,e,ee) : ee; ! 970: } ! 971: slow = 1; ! 972: first = 0; ! 973: continue; ! 974: } ! 975: Ptype mt = m->tp; ! 976: tx: ! 977: switch (mt->base) { ! 978: case TYPE: ! 979: mt = Pbase(mt)->b_name->tp; ! 980: goto tx; ! 981: case VEC: ! 982: { Pname cn = Pvec(mt)->typ->is_cl_obj(); ! 983: if (cn && Pclass(cn->tp)->c_xref&(C_ASS|C_VBASE)) { ! 984: error('s',"copy of %n[], no memberwise copy for%n",cn,cn); ! 985: slow = 1; // make sure an assignment operator ! 986: // is generated so that there will ! 987: // be no more error messages ! 988: } ! 989: ! 990: if (slow && mt->tsizeof()) { ! 991: // protect against sizeof(mt)==0: char[] ! 992: /* ! 993: generate: ! 994: struct _s { char[sizeof(m)]; }; ! 995: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 996: */ ! 997: Pexpr l = new name(m->string); ! 998: Pexpr r = new name(m->string); ! 999: r = new ref(DOT,new name(arg->string),r); ! 1000: Pexpr ee = copy_obj(l,r,mt->tsizeof()); ! 1001: e = e ? new expr(CM,e,ee) : ee; ! 1002: break; ! 1003: } ! 1004: } ! 1005: case FCT: ! 1006: case OVERLOAD: ! 1007: case CLASS: ! 1008: case ENUM: ! 1009: break; ! 1010: case RPTR: ! 1011: error("cannot assignC%t:RM%n",cl,m); ! 1012: break; ! 1013: case COBJ: ! 1014: //error('d',"cobj %n %d %d",m,slow,Pclass(Pbase(mt)->b_name->tp)->c_xref); ! 1015: if (slow==0 ! 1016: && Pclass(Pbase(mt)->b_name->tp)->c_xref&(C_VBASE|C_ASS)) { ! 1017: // must use its assignment operation ! 1018: if (first==0 && m->n_offset) { ! 1019: // copy up to this member ! 1020: Pexpr th = new expr(THIS,0,0); ! 1021: Pexpr a = new name(arg->string); ! 1022: a = a->address(); ! 1023: e = copy_obj(th,a,m->n_offset); ! 1024: } ! 1025: slow = 1; ! 1026: } ! 1027: // no break: copy cobj itself ! 1028: default: ! 1029: //error('d',"defa %n %d",m,slow); ! 1030: if (slow) { ! 1031: if (m->tp->tconst()) error("cannot assignC%t: const M%n",cl,m); ! 1032: Pname ms = new name(m->string); ! 1033: Pname as = new name(arg->string); ! 1034: Pexpr ee = new ref(DOT,as,new name(m->string)); ! 1035: ee = new expr(ASSIGN,ms,ee); ! 1036: e = e ? new expr(CM,e,ee) : ee; ! 1037: } ! 1038: } ! 1039: first = 0; ! 1040: } ! 1041: ! 1042: if (slow == 0) { ! 1043: /* really simple just copy: ! 1044: */ ! 1045: //error('d',"slow"); ! 1046: /* ! 1047: Pexpr th = new expr(THIS,0,0); ! 1048: Pexpr a = new name(arg->string); ! 1049: a = a->address(); ! 1050: Pexpr ee = copy_obj(th,a,cl->tsize()); ! 1051: e = e ? new expr(CM,e,ee) : e; ! 1052: */ ! 1053: //error('d',"%n simple assignment",cn); ! 1054: // cl->c_xref ^= C_ASS; // Didn't mean it: No X::operator=(X&) ! 1055: return 0; ! 1056: } ! 1057: ! 1058: } ! 1059: ! 1060: Pexpr rv = new expr(THIS,0,0); ! 1061: rv = new expr(DEREF,rv,0);//b1->contents(); ! 1062: ! 1063: s->e = e ? new expr(CM,e,rv) : e; ! 1064: s->s_list = new estmt(RETURN,no_where,rv,0); ! 1065: ! 1066: cc->stack(); ! 1067: cc->not = cn; ! 1068: cc->cot = cl; ! 1069: ! 1070: cl->c_xref |= C_ASS; // now it has X::operator=(const X&) ! 1071: ! 1072: Pname fn = new name(oper_name(ASSIGN)); ! 1073: Pfct f = new fct(new ptr(RPTR,Pptr(cl->this_type)->typ),arg,1); ! 1074: f->f_inline = 1; ! 1075: fn->tp = f; ! 1076: fn->n_oper = ASSIGN; ! 1077: fn->n_sto = STATIC; ! 1078: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 1079: delete fn; ! 1080: Pfct(nn->tp)->body = new block(curloc,0,s); ! 1081: Pfct(nn->tp)->dcl(nn); ! 1082: ! 1083: cc->unstack(); ! 1084: nn->simpl(); ! 1085: //error('d',"make_assign->"); ! 1086: return 1; ! 1087: } ! 1088: ! 1089: void classdef::dcl(Pname cname, Ptable tbl) ! 1090: { ! 1091: int bvirt = 0; ! 1092: int dvirt = 0; ! 1093: int scope = PUBLIC; ! 1094: int protect = 0; ! 1095: int st = 1; // nothing private or protected seen: a struct ! 1096: ! 1097: int byte_old = byte_offset; ! 1098: int bit_old = bit_offset; ! 1099: int max_old = max_align; ! 1100: int boff = 0; ! 1101: ! 1102: int in_union = 0; ! 1103: int usz; ! 1104: int make_ctor = 0; ! 1105: int make_dtor = 0; ! 1106: ! 1107: /* this is the place for paranoia */ ! 1108: if (this == 0) error('i',"0->Cdef::dcl(%p)",tbl); ! 1109: if (base != CLASS) error('i',"Cdef::dcl(%d)",base); ! 1110: if (cname == 0) error('i',"unNdC"); ! 1111: if (cname->tp != this) error('i',"badCdef"); ! 1112: if (tbl == 0) error('i',"Cdef::dcl(%n,0)",cname); ! 1113: if (tbl->base != TABLE) error('i',"Cdef::dcl(%n,tbl=%d)",cname,tbl->base); ! 1114: //error('d',"classdef %s tbl %d gtbl %d",string,tbl,gtbl); ! 1115: ! 1116: switch (csu) { ! 1117: case UNION: ! 1118: case ANON: ! 1119: in_union = 1; ! 1120: break; ! 1121: case CLASS: ! 1122: scope = 0; ! 1123: } ! 1124: ! 1125: max_align = AL_STRUCT; ! 1126: ! 1127: // local classes ! 1128: //error('d', "classdef(): lex_level: %d nof: %n", lex_level, cc->nof); ! 1129: if (lex_level) { ! 1130: in_fct = cc->nof; ! 1131: // local classes at lex_level==1 ! 1132: if ( lcl == 0 ) lcl = make_name( 'L' ); ! 1133: } ! 1134: ! 1135: if (strlen == 0) strlen = ::strlen(string); ! 1136: ! 1137: if (baselist) { ! 1138: /* ! 1139: check base classes. ! 1140: duplicates were removed in start_cl() in norm.c. ! 1141: remove bad classes. ! 1142: add virtual bases from bases to the list. ! 1143: ! 1144: check against ! 1145: class b : a {} ! 1146: class c : a, b {} // first a inaccessible ! 1147: */ ! 1148: ! 1149: Pbcl ll = 0; ! 1150: Pbcl lll = 0; ! 1151: Pbcl vlist = 0; ! 1152: for (Pbcl lx, l=baselist; l; l=lx) { // remove bad bases ! 1153: Pclass cl = l->bclass; ! 1154: lx = l->next; ! 1155: ! 1156: //error('d',"base1 %t %k init %d",cl,l->ppp,l->init); ! 1157: // ``class'' => private base ``struct'' => public base ! 1158: if (l->ppp == 0) { ! 1159: l->ppp = csu==CLASS ? PRIVATE : PUBLIC; ! 1160: #ifndef OLD ! 1161: if (l->ppp == PRIVATE) error('w',"B%t private by default: please be explicit ``: private%t",cl,cl); ! 1162: #endif ! 1163: } ! 1164: // if you have a ``class'' as base you cannot remain a ! 1165: // ``mere struct'' ! 1166: if (cl && cl->csu == CLASS) st = 0; ! 1167: ! 1168: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1169: error("BC %sU",cl->string); ! 1170: continue; ! 1171: } ! 1172: else ! 1173: (void)cl->tsizeof(); // ensure printout ! 1174: ! 1175: if (cl->csu==UNION || cl->csu==ANON) { ! 1176: error("C derived from union"); ! 1177: continue; ! 1178: } ! 1179: ! 1180: if (in_union) { ! 1181: error("derived union"); ! 1182: continue; ! 1183: } ! 1184: ! 1185: if (l->base==VIRTUAL) { ! 1186: if (cl->has_ictor()==0 && cl->has_ctor()) { ! 1187: error("virtualB%t has no defaultIr",cl); ! 1188: continue; ! 1189: } ! 1190: // order of virtual classes doesn't matter ! 1191: l->next = vlist; ! 1192: vlist = l; ! 1193: } ! 1194: else { // keep ordinary base classes in order ! 1195: if (ll == 0) { ! 1196: lll = l; ! 1197: l->next = 0; ! 1198: } ! 1199: else ! 1200: ll->next = l; ! 1201: ll = l; ! 1202: } ! 1203: } ! 1204: if (ll) { ! 1205: ll->next = vlist; // put virtual bases at end ! 1206: baselist = lll; ! 1207: } ! 1208: else ! 1209: baselist = vlist; ! 1210: ! 1211: lll = 0; ! 1212: for (l=baselist; l; l=l->next) { // detect unmanageable duplicates ! 1213: Pclass b = l->bclass; ! 1214: for (ll=baselist; ll; ll=ll->next) ! 1215: if (b!=ll->bclass && ll->bclass->check_dup(b,l->base)) { ! 1216: if (lll) ! 1217: lll->next = l->next; ! 1218: else ! 1219: baselist = l->next; ! 1220: goto mmm; ! 1221: } ! 1222: ! 1223: lll = l; ! 1224: mmm:; ! 1225: } ! 1226: ! 1227: for (l=baselist; l; l=l->next) { // promote virtual bases ! 1228: Pclass b = l->bclass; ! 1229: for (ll=b->baselist; ll; ll=ll->next) { ! 1230: if (ll->base == VIRTUAL) { ! 1231: Pclass v = ll->bclass; ! 1232: for (Pbcl lll=baselist; lll; lll=lll->next) ! 1233: if (lll->bclass == v) goto nnn; ! 1234: // error('w',"%t is virtualB of%t",v,this); ! 1235: baselist = new basecl(v,baselist); ! 1236: baselist->base = VIRTUAL; ! 1237: baselist->promoted = 1; ! 1238: // needs a more complete check of visibility rules ! 1239: //error('d',"promote %t %k",v,ll->ppp); ! 1240: baselist->ppp = ll->ppp; ! 1241: } ! 1242: nnn:; ! 1243: } ! 1244: } ! 1245: ! 1246: ll = 0; ! 1247: lll = 0; ! 1248: l=baselist; ! 1249: baselist = 0; ! 1250: vlist = 0; ! 1251: for (; l; l=lx) { ! 1252: // sort virtual bases so that no virtual base ! 1253: // is ahead of its own virtual base ! 1254: lx = l->next; ! 1255: if (l->base == VIRTUAL) { // add to sorted vlist ! 1256: // each class before its bases ! 1257: if (vlist == 0) { ! 1258: vlist = l; ! 1259: l->next = 0; ! 1260: } ! 1261: else { ! 1262: Pclass lb = l->bclass; ! 1263: Pbcl v_prev = 0; ! 1264: for (Pbcl vx, v = vlist; v; v=vx) { ! 1265: Pclass vb = v->bclass; ! 1266: vx = v->next; ! 1267: ! 1268: if (lb->has_base(vb)) { ! 1269: // put l ahead of v ! 1270: l->next = v; ! 1271: if (v_prev) ! 1272: v_prev->next = l; ! 1273: else ! 1274: vlist = l; ! 1275: break; ! 1276: } ! 1277: if (vx == 0) { ! 1278: // stick l at end ! 1279: v->next = l; ! 1280: l->next = 0; ! 1281: break; ! 1282: } ! 1283: v_prev = v; ! 1284: } ! 1285: } ! 1286: } ! 1287: else { // keep in order ! 1288: if (ll == 0) { ! 1289: lll = l; ! 1290: l->next = 0; ! 1291: } ! 1292: else ! 1293: ll->next = l; ! 1294: ll = l; ! 1295: } ! 1296: } ! 1297: ! 1298: if (ll) { ! 1299: ll->next = vlist; // put virtual bases at end ! 1300: baselist = lll; ! 1301: } ! 1302: else ! 1303: baselist = vlist; ! 1304: ! 1305: for (l=baselist; l; l=l->next) { // allocate base class objects ! 1306: Pclass cl = l->bclass; ! 1307: //error('d',"base %t %k init %d",cl,l->ppp,l->init); ! 1308: if (l->base == VIRTUAL) { // : virtual bclass ! 1309: // pointer and object for virtual base MAY ! 1310: // be allocated at the end - but not here ! 1311: c_xref |= C_VBASE; ! 1312: dvirt += cl->virt_count; ! 1313: } ! 1314: else { // : bclass =>allocate ! 1315: int ba = cl->align(); ! 1316: if (max_align<ba) max_align = ba; ! 1317: ! 1318: if (cl == baselist->bclass) { // pad to ensure alignment: ! 1319: boff = cl->real_size; ! 1320: int xtra = boff%ba; // not obj_size-real_size, we can ! 1321: // optimize vbase object away ! 1322: if (xtra) boff += ba-xtra; // align ! 1323: } ! 1324: else { // let C handle the padding: ! 1325: int xtra = boff%ba; ! 1326: if (xtra) boff += ba-xtra; // align ! 1327: l->obj_offset = boff; ! 1328: boff += cl->obj_size; // don't use waste ! 1329: } ! 1330: bvirt += cl->virt_count; ! 1331: } ! 1332: ! 1333: if (cl->has_vvtab) has_vvtab = 1; ! 1334: c_xref |= cl->c_xref; ! 1335: ! 1336: //error('d',"%t: base %t conv %d base conv %d",this,cl,conv,cl->conv); ! 1337: conv = merge_conv(conv,cl->conv); ! 1338: } ! 1339: } ! 1340: ! 1341: memtbl->set_name(cname); ! 1342: ! 1343: // int nmem = mem_list->no_of_names(); ! 1344: int nmem = 0; ! 1345: int fct_mem = 0; ! 1346: { for (Pname m = mem_list; m; m=m->n_list) { ! 1347: nmem++; ! 1348: if (m->tp && m->tp->base==FCT) fct_mem++; ! 1349: } ! 1350: } ! 1351: if (nmem) memtbl->grow((nmem<=2)?3:nmem); ! 1352: ! 1353: cc->stack(); ! 1354: cc->not = cname; ! 1355: cc->cot = this; ! 1356: ! 1357: byte_offset = usz = boff; ! 1358: bit_offset = 0; ! 1359: ! 1360: ! 1361: Pbase bt = new basetype(COBJ,cname); ! 1362: bt->b_table = memtbl; ! 1363: Ptype cct = bt->addrof(); ! 1364: if (strict_opt) Pptr(cct)->rdo = 1; // type of `this': X *const ! 1365: this_type = cc->tot = cct; ! 1366: PERM(cct); ! 1367: PERM(bt); ! 1368: ! 1369: for (Pname px, p=mem_list; p; p=px) { ! 1370: /* ! 1371: look at each member; ! 1372: declare it and determine its visibility ! 1373: calculate offsets and sizes ! 1374: */ ! 1375: px = p->n_list; ! 1376: ! 1377: switch (p->base) { ! 1378: case PUBLIC: ! 1379: scope = PUBLIC; ! 1380: protect = 0; ! 1381: goto prpr; ! 1382: ! 1383: case PRIVATE: ! 1384: scope = 0; ! 1385: protect = 0; ! 1386: goto prpr; ! 1387: ! 1388: case PROTECTED: ! 1389: scope = 0; ! 1390: protect = PROTECTED; ! 1391: prpr: ! 1392: if (in_union) error("%k in unionD",p->base); ! 1393: continue; ! 1394: ! 1395: case PR: // visibility control: C::M ! 1396: { ! 1397: char* qs = p->n_qualifier->string; ! 1398: char* ms = p->string; ! 1399: TOK ppp = scope?PUBLIC:(protect?PROTECTED:PRIVATE); ! 1400: ! 1401: p->base = NAME; ! 1402: p->n_scope = scope; ! 1403: p->n_protect = protect; ! 1404: ! 1405: if (strcmp(ms,qs) == 0) ms = "__ct"; ! 1406: ! 1407: extern ppbase; ! 1408: ppbase = PUBLIC; ! 1409: ! 1410: if (is_base(qs) == 0) { ! 1411: error("%kQr %s not aBC of %s",ppp,qs,string); ! 1412: continue; ! 1413: } ! 1414: ! 1415: extern int mex; ! 1416: extern Pclass mec; ! 1417: extern Pclass tcl; ! 1418: extern Pname me; ! 1419: extern Pfct mef; ! 1420: mex = 1; ! 1421: tcl = mec = this; ! 1422: me = 0; ! 1423: mef = 0; ! 1424: c_body = 0; // this search must not be interpreted as a use ! 1425: Pname os = Cdcl; ! 1426: Cdcl = p; ! 1427: Pexpr ee = find_name(ms,0); ! 1428: Cdcl = os; ! 1429: c_body = 1; ! 1430: ! 1431: // while (ee->base == MDOT || ee->base == REF) ! 1432: while (ee && (ee->base == MDOT || ee->base == REF)) ! 1433: ee = ee->mem; ! 1434: Pname mx = Pname(ee); ! 1435: ! 1436: if (mx == 0) { ! 1437: error("C %s does not have aM %s",qs,ms); ! 1438: continue; ! 1439: } ! 1440: ! 1441: if (mx->tp->base == OVERLOAD) { ! 1442: error('s',"%k specification of overloaded%n",ppp,mx); ! 1443: continue; ! 1444: } ! 1445: ! 1446: TOK pp = mx->n_scope?PUBLIC:mx->n_protect?PROTECTED:PRIVATE; ! 1447: ! 1448: //error('d',"mx %n pp %k ppp %k",mx,pp,ppp); ! 1449: if (ppp != pp) { ! 1450: error(&p->where,"%kM%n specified%k",pp,mx,ppp); ! 1451: continue; ! 1452: } ! 1453: ! 1454: ! 1455: p->n_qualifier = mx; ! 1456: Pname m = memtbl->insert(p,0); ! 1457: m->base = PUBLIC; ! 1458: if (Nold) error("twoDs of CM%n",p); ! 1459: continue; ! 1460: } ! 1461: } ! 1462: ! 1463: //error('d',"mem%n %d scope %d n_sto %k",p,p->tp->base,scope,p->n_sto); ! 1464: if (scope==0) st = 0; ! 1465: ! 1466: if (p->tp->base == FCT) { ! 1467: int ff = 0; ! 1468: Pfct f = Pfct(p->tp); ! 1469: Pblock b = f->body; ! 1470: f->body = 0; ! 1471: if (b) f->f_inline = 1; ! 1472: switch (p->n_sto) { ! 1473: case FRIEND: ! 1474: ff = 1; ! 1475: break; ! 1476: case STATIC: // accept static member functions ! 1477: //error('d',"inline %d",f->f_inline); ! 1478: // if (f->f_inline==0) ! 1479: f->f_static = 1; ! 1480: p->n_sto = 0; ! 1481: break; ! 1482: case AUTO: ! 1483: // case STATIC: ! 1484: case REGISTER: ! 1485: case EXTERN: ! 1486: error("M%n cannot be%k",p,p->n_sto); ! 1487: p->n_sto = 0; ! 1488: } ! 1489: Pname m = p->dcl(memtbl,scope); ! 1490: if (m == 0) continue; ! 1491: //error('d',"p %n %t %d",m,f,m->n_initializer); ! 1492: if (m->n_initializer) c_abstract = 1; ! 1493: //error('d',"mem %n: %t ff %d protect %k",m,m->tp,ff,protect); ! 1494: if (ff == 0) m->n_protect = protect; ! 1495: if (b) { ! 1496: //error('d',"b line %d %d defined %d",p->where.line,m->where.line,m->tp->defined); ! 1497: if (m->tp->defined&(DEFINED|SIMPLIFIED)) ! 1498: error("two definitions of%n",m); ! 1499: else ! 1500: Pfct(m->tp)->body = b; ! 1501: // Pfct(m->tp)->f_inline = 1; ! 1502: } ! 1503: if (ff==0 && p->where.line!=m->where.line) ! 1504: error("%n cannot be redeclared inCD",p); ! 1505: } ! 1506: else { ! 1507: Eppp = scope?scope:protect?protect:0; ! 1508: ! 1509: if (p->base == TNAME) { // typedef names are exported ! 1510: // to surrounding scope ! 1511: // NOT complete: should go to ! 1512: // surrounding non-class scope ! 1513: p->dcl(tbl,scope); ! 1514: ! 1515: // typedefs need to be generated outside class ! 1516: if ( p->tp && Pbase(p->tp)->base != COBJ ) { ! 1517: Pname n = gtbl->look(p->string,0); ! 1518: if ( n && lex_level == 0 && n->base != TNAME ) ! 1519: error("%nredefined: identifier and typedef",p); ! 1520: p->dcl_print(0); ! 1521: } ! 1522: continue; ! 1523: }; ! 1524: ! 1525: if (p->n_initializer) { ! 1526: error("Ir forM%n",p); ! 1527: p->n_initializer = 0; ! 1528: } ! 1529: ! 1530: // error('d',"lex_level: %d p %n lex %d",lex_level, p,p->lex_level); ! 1531: extern Ptable lcl_tbl; ! 1532: if ( lex_level && p->tp->base == VEC ) lcl_tbl = tbl; ! 1533: Pname m = p->dcl(memtbl,scope); ! 1534: lcl_tbl = 0; ! 1535: Eppp = 0; ! 1536: if (m == 0) continue; ! 1537: ! 1538: m->n_protect = protect; ! 1539: ! 1540: if (m->n_stclass==STATIC) { ! 1541: extern Plist stat_mem_list; ! 1542: if (in_union) error("staticM%n in union",m); ! 1543: // Ptype t = m->tp; ! 1544: // Pname cn = t->is_cl_obj(); ! 1545: // if ((cn && Pclass(cn->tp)->has_ctor()) ! 1546: // || t->is_ref() ! 1547: // || (t->tconst() && vec_const == 0)) ! 1548: m->n_sto = EXTERN; ! 1549: if (tbl == gtbl) stat_mem_list = new name_list(m,stat_mem_list); ! 1550: if (m->n_initializer) error('s',"staticM%nWIr",m); ! 1551: } ! 1552: ! 1553: if (in_union) { ! 1554: if (usz < byte_offset) usz = byte_offset; ! 1555: byte_offset = 0; ! 1556: } ! 1557: } ! 1558: } ! 1559: ! 1560: if (st && csu==CLASS) csu = STRUCT; // nothing private => STRUCT ! 1561: ! 1562: if (in_union) byte_offset = usz; ! 1563: ! 1564: // now look look at the members ! 1565: ! 1566: Pname ct = has_ctor(); ! 1567: Pname dt = has_dtor(); ! 1568: int i; ! 1569: ! 1570: extern int mex; ! 1571: int omex = mex; mex = 0; ! 1572: Pname on = has_oper(NEW); ! 1573: Pname od = has_oper(DELETE); ! 1574: mex = omex; ! 1575: ! 1576: if (dt && ct==0) error('w',"%s has%n but noK",string,dt); ! 1577: if (on && od==0) error('w',"%s has%n but no operator delete()",string,on); ! 1578: if (od && on==0) error('w',"%s has%n but no operator new()",string,od); ! 1579: ! 1580: if (dt==0 && od && od && od->n_table==memtbl) make_dtor = 1; ! 1581: ! 1582: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 1583: /* ! 1584: The members have been declared. ! 1585: now look at each to see if it needs defining ! 1586: */ ! 1587: Ptype t = m->tp; ! 1588: ! 1589: if (t == 0) continue; // public declarations ! 1590: ! 1591: switch (t->base) { ! 1592: default: ! 1593: if (ct==0 ! 1594: && m->n_stclass!=ENUM ! 1595: && m->n_stclass!=STATIC) { ! 1596: if (t->is_ref()) error("R%n inC %sWoutK",m,string); ! 1597: if (t->tconst() ! 1598: && vec_const==0 ! 1599: && m->n_evaluated==0) ! 1600: error("const%n inC %sWoutK",m,string); ! 1601: } ! 1602: case VEC: ! 1603: break; ! 1604: case FCT: ! 1605: case OVERLOAD: ! 1606: case CLASS: ! 1607: case ENUM: ! 1608: continue; ! 1609: } ! 1610: ! 1611: Pname cn = t->is_cl_obj(); ! 1612: if (cn == 0) cn = cl_obj_vec; ! 1613: if (cn == 0) continue; ! 1614: ! 1615: Pclass cl = Pclass(cn->tp); ! 1616: c_xref |= cl->c_xref; ! 1617: //error('d',"m %n %t %d",m,cl,cl->c_xref); ! 1618: if (cl->has_ctor()) { ! 1619: if (m->n_stclass == STATIC) ! 1620: ; // error('s',"staticM%n ofC%nWK",m,cn); ! 1621: else if (in_union) ! 1622: error("M%n ofC%nWK in union",m,cn); ! 1623: else if (ct == 0) { ! 1624: // does mctor have a default constructor? ! 1625: if (make_ctor==0 && cl->has_ictor()==0) ! 1626: error("%t needs aK; it has aMWK requiringAs",this); ! 1627: make_ctor = 1; ! 1628: } ! 1629: } ! 1630: ! 1631: if (cl->has_dtor()) { ! 1632: if (m->n_stclass==STATIC) ! 1633: ; // error('s',"staticM%n ofC%nW destructor",m,cn); ! 1634: else if (in_union) ! 1635: error("M%n ofC%nW destructor in union",m,cn); ! 1636: else if (dt==0) ! 1637: make_dtor = 1; ! 1638: } ! 1639: } ! 1640: ! 1641: if (has_dtor()==0 && make_dtor==0) { ! 1642: // can dtor be inherited (from single base class)? ! 1643: Pclass bcl = 0; ! 1644: for (Pbcl b = baselist; b; b = b->next) { ! 1645: switch (b->base) { ! 1646: case NAME: ! 1647: if (bcl == 0) { ! 1648: Pname d = b->bclass->has_dtor(); ! 1649: if (d==0) break; ! 1650: if (strict_opt == 0) { ! 1651: if (d->n_scope==PUBLIC ! 1652: && Pfct(d->tp)->f_virtual==0) { ! 1653: bcl = b->bclass; ! 1654: break; ! 1655: } ! 1656: } ! 1657: } ! 1658: // two dtors or non-public dtors force creation ! 1659: make_dtor = 1; ! 1660: goto zbzb; ! 1661: case VIRTUAL: ! 1662: if (b->bclass->has_dtor()) make_dtor = 1; ! 1663: goto zbzb; ! 1664: } ! 1665: } ! 1666: if (bcl) c_dtor = bcl->has_dtor(); ! 1667: zbzb:; ! 1668: } ! 1669: ! 1670: if (make_dtor && dt==0) { // make x::~x() {} ! 1671: ! 1672: // must be done before vtbls are made in case dtor is virtual ! 1673: //error('d',"%t: make_dtor",this); ! 1674: Pname n = new name(string); ! 1675: Pfct f = new fct(defa_type,0,1); ! 1676: f->f_inline = /*IDTOR; */ 1; ! 1677: n->tp = f; ! 1678: n->n_oper = DTOR; ! 1679: dt = n->dcl(memtbl,PUBLIC); ! 1680: delete n; ! 1681: Pfct(dt->tp)->body = /*0; */ new block(curloc,0,0); ! 1682: dt = has_dtor(); ! 1683: } ! 1684: ! 1685: if (virt_count && find_vptr(this)==0) { ! 1686: // we only need a vptr if this class ! 1687: // has virtual functions and none ! 1688: // of its first bases have vptrs ! 1689: //error('d',"%s virt_count %d",string,virt_count); ! 1690: extern Ptype Pvptr_type; ! 1691: Pname vp = new name("__vptr"); ! 1692: vp->tp = Pvptr_type; ! 1693: (void) vp->dcl(memtbl,0); ! 1694: delete vp; ! 1695: c_xref |= C_VPTR; ! 1696: } ! 1697: else ! 1698: // no more bit fields. absorb bit_offset ! 1699: if (bit_offset) byte_offset += (bit_offset/BI_IN_BYTE+1); ! 1700: ! 1701: for (Pbcl b = baselist; b; b = b->next) { // allocate virtual base pointers ! 1702: if (b->base != VIRTUAL) continue; ! 1703: Pclass bcl = b->bclass; ! 1704: ! 1705: // search non-virtual bases for this virtual base ! 1706: for (Pbcl bb = baselist; bb; bb = bb->next) ! 1707: if (bb->base == NAME) { ! 1708: for (Pbcl l = bb->bclass->baselist; l; l=l->next) ! 1709: if (l->base==VIRTUAL && l->bclass==bcl) goto eee; ! 1710: } ! 1711: { ! 1712: if (obj_align<AL_WPTR) obj_align = AL_WPTR; ! 1713: if (max_align<AL_WPTR) max_align = AL_WPTR; ! 1714: int waste = byte_offset%AL_WPTR; ! 1715: if (waste) byte_offset += AL_WPTR-waste; // align ! 1716: b->ptr_offset = byte_offset+1; // ensure != 0 ! 1717: byte_offset += sizeof(int*); ! 1718: } ! 1719: eee:; ! 1720: } ! 1721: ! 1722: real_size = byte_offset; // the rest may be optimized away ! 1723: ! 1724: for (b = baselist; b; b = b->next) { // allocate virtual class objects ! 1725: if (b->base != VIRTUAL) continue; ! 1726: Pclass bcl = b->bclass; ! 1727: ! 1728: // if necessary ! 1729: if (b->obj_offset = has_allocated_base(bcl)) continue; ! 1730: ! 1731: int ba = bcl->align(); ! 1732: if (obj_align<ba) obj_align = ba; ! 1733: if (max_align<ba) max_align = ba; ! 1734: int waste = byte_offset%ba; ! 1735: if (waste) byte_offset += ba-waste; // align ! 1736: b->obj_offset = byte_offset; // offset in this ! 1737: b->allocated = 1; ! 1738: //error('d',"virtual %t in %t at %d",bcl,this,b->obj_offset); ! 1739: byte_offset += bcl->tsizeof(); ! 1740: } ! 1741: ! 1742: // no more data members. ! 1743: // pad object (so that copying into a base object ! 1744: // doesn't destroy derevid class members): ! 1745: if (byte_offset==0) { // empty struct: waste a member ! 1746: Pname c = new name (make_name('W')); ! 1747: c->tp = char_type; ! 1748: (void) c->dcl(memtbl,0); ! 1749: real_size = byte_offset = 1; ! 1750: } ! 1751: if (byte_offset < SZ_STRUCT) byte_offset = SZ_STRUCT; ! 1752: int waste = byte_offset%max_align; ! 1753: if (waste) byte_offset += max_align-waste; ! 1754: obj_size = byte_offset; ! 1755: obj_align = max_align; ! 1756: ! 1757: // make vtbls ! 1758: // this cannot be done until the bases ! 1759: // have been allocated in this class ! 1760: // so that the offsets (deltas) are known ! 1761: if (all_virt(this,0,1,0)) { ! 1762: if (has_ctor()==0) make_ctor = 1; ! 1763: } ! 1764: else if (has_vvtab) ! 1765: error("virtualB: conflicting vtable initialization"); ! 1766: ! 1767: Pname hito = has_itor(); ! 1768: ! 1769: if (hito) c_xref |= C_XREF; // has user defined X(X&) ! 1770: //error('d',"%t hito %d ctor %d",this,hito,make_ctor); ! 1771: if (hito==0 && c_xref&(C_VPTR|C_VBASE|C_XREF)) { ! 1772: // X(X&) needed if bitwise copy is illegal ! 1773: // or if any constructor is defined ! 1774: ! 1775: hito = make_itor(0); ! 1776: // if the base has B::B(void) ! 1777: // the derived should have D::D(void) ! 1778: if (baselist) { ! 1779: int mc = 1; // can make and ictor ! 1780: for (Pbcl b = baselist; b; b = b->next) { ! 1781: if (b->bclass->has_ctor() ! 1782: && b->bclass->has_ictor()==0) ! 1783: mc = 0; ! 1784: } ! 1785: make_ctor = mc; ! 1786: /* ! 1787: int mc = 1; // can make an ictor ! 1788: for (Pbcl b = baselist; b; b = b->next) { ! 1789: if (b->bclass->has_ctor()) { ! 1790: Pname c = b->bclass->has_ictor(); ! 1791: // no copy constructor? ! 1792: // non-public copy constructor? ! 1793: if (c==0 || c->n_scope==0) mc = 0; ! 1794: } ! 1795: } ! 1796: make_ctor = mc; ! 1797: */ ! 1798: } ! 1799: else ! 1800: make_ctor = 1; ! 1801: } ! 1802: ! 1803: if (c_ctor==0 && make_ctor==0) { // can ctor be inherited (from single base class)? ! 1804: /* ! 1805: int bb = 0; ! 1806: for (Pbcl b = baselist; b; b = b->next) { ! 1807: switch (b->base) { ! 1808: case NAME: ! 1809: { Pname c = b->bclass->has_ctor(); ! 1810: // if (b->bclass->has_ctor() == 0) break; ! 1811: if (c == 0) break; ! 1812: if (c->n_scope==PUBLIC && bb++==0) break; ! 1813: } ! 1814: // no break: two bases: needs ctor ! 1815: case VIRTUAL: ! 1816: make_ctor = 1; // virtual base: need ctor ! 1817: goto zaza; ! 1818: } ! 1819: } ! 1820: */ ! 1821: Pname btor = 0; ! 1822: Pclass bc = 0; ! 1823: for (Pbcl b = baselist; b; b = b->next) { ! 1824: switch (b->base) { ! 1825: case NAME: ! 1826: { Pname c = b->bclass->has_ctor(); ! 1827: if (c == 0) break; ! 1828: if (c->n_scope==PUBLIC && b==baselist) { ! 1829: bc = b->bclass; ! 1830: btor = bc->has_ictor(); ! 1831: break; ! 1832: } ! 1833: } ! 1834: // no break: two bases: needs ctor ! 1835: case VIRTUAL: ! 1836: make_ctor = 1; // virtual base: need ctor ! 1837: goto zaza; ! 1838: } ! 1839: } ! 1840: // c_ctor = btor; ! 1841: //error('d',"btor %n",btor); ! 1842: if (bc) { ! 1843: if (btor) ! 1844: make_ctor = 1; ! 1845: else ! 1846: error("K needed for %s, BC%t hasK",string,bc); ! 1847: } ! 1848: zaza:; ! 1849: } ! 1850: ! 1851: if (make_ctor && ct==0) { // make x::x() {} ! 1852: //error('d',"%t: make_ctor",this); ! 1853: Pname n = new name(string); ! 1854: Pfct f = new fct(defa_type,0,1); ! 1855: f->f_inline = 1; // ICTOR; // ICTOR means ``define ctor() if used'' ! 1856: n->tp = f; ! 1857: n->n_oper = TNAME; ! 1858: ct = n->dcl(memtbl,PUBLIC); ! 1859: delete n; ! 1860: Pfct(ct->tp)->body = /* 0; */ new block(curloc,0,0); ! 1861: } ! 1862: ! 1863: defined |= DEFINED; ! 1864: ! 1865: if (ansi_opt) { ! 1866: char* s = csu==UNION || csu==ANON ? "union" : "struct"; ! 1867: fprintf(out_file,"%s %s;",s,string); ! 1868: } ! 1869: //error('d',"defined %s",string); ! 1870: ! 1871: // fix argument lists for inlines ! 1872: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { ! 1873: Pfct f = Pfct(p->tp); ! 1874: if (f==0) continue; // public declarations ! 1875: ! 1876: switch (f->base) { ! 1877: case FCT: ! 1878: if (hito && f->argtype) fix_args(f,this); ! 1879: if (p->n_oper == CTOR) f->s_returns = this_type; ! 1880: if (f->body) { ! 1881: p->n_sto = STATIC; ! 1882: // if (debug_opt) p->dcl_print(0); ! 1883: } ! 1884: break; ! 1885: case OVERLOAD: ! 1886: { Pgen g = Pgen(f); ! 1887: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 1888: Pname n = gl->f; ! 1889: Pfct f = Pfct(n->tp); ! 1890: ! 1891: if (hito && f->argtype) fix_args(f,this); ! 1892: if (n->n_oper == CTOR) f->s_returns = this_type; ! 1893: if (f->body) { ! 1894: n->n_sto = STATIC; ! 1895: // if (debug_opt) n->dcl_print(0); ! 1896: } ! 1897: } ! 1898: } ! 1899: } ! 1900: } ! 1901: //error('d',"args_fixed"); ! 1902: ! 1903: // define members defined inline ! 1904: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { ! 1905: Pfct f = Pfct(p->tp); ! 1906: if (f==0) continue; // public declarations ! 1907: ! 1908: switch (f->base) { ! 1909: case FCT: ! 1910: if (f->body) { ! 1911: f->dcl(p); ! 1912: p->simpl(); ! 1913: if (debug_opt) p->dcl_print(0); ! 1914: } ! 1915: break; ! 1916: case OVERLOAD: ! 1917: { Pgen g = Pgen(f); ! 1918: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 1919: Pname n = gl->f; ! 1920: Pfct f = Pfct(n->tp); ! 1921: ! 1922: if (f->body) { ! 1923: f->dcl(n); ! 1924: n->simpl(); ! 1925: if (debug_opt) p->dcl_print(0); ! 1926: } ! 1927: } ! 1928: } ! 1929: } ! 1930: } ! 1931: //error('d',"functions defined"); ! 1932: byte_offset = byte_old; ! 1933: bit_offset = bit_old; ! 1934: max_align = max_old; ! 1935: ! 1936: cc->unstack(); // friends are not in class scope ! 1937: ! 1938: // define friends defined inline and modify return types if necessary ! 1939: for (Plist fl=friend_list; fl; fl=fl->l) { ! 1940: Pname p = fl->f; ! 1941: Pfct f = Pfct(p->tp); ! 1942: ! 1943: switch (f->base) { ! 1944: case FCT: ! 1945: if (hito && f->argtype) fix_args(f,this); ! 1946: if (f->body ! 1947: && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1948: p->n_sto = STATIC; ! 1949: // if (debug_opt) p->dcl_print(0); ! 1950: } ! 1951: break; ! 1952: case OVERLOAD: ! 1953: { Pgen g = Pgen(f); ! 1954: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 1955: Pname n = gl->f; ! 1956: Pfct f = Pfct(n->tp); ! 1957: ! 1958: if (hito && f->argtype) fix_args(f,this); ! 1959: if (f->body ! 1960: && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1961: n->n_sto = STATIC; ! 1962: // if (debug_opt) n->dcl_print(0); ! 1963: } ! 1964: } ! 1965: } ! 1966: } ! 1967: } ! 1968: ! 1969: // define friends defined inline and modify return types if necessary ! 1970: for (fl=friend_list; fl; fl=fl->l) { ! 1971: Pname p = fl->f; ! 1972: Pfct f = Pfct(p->tp); ! 1973: ! 1974: switch (f->base) { ! 1975: case FCT: ! 1976: if (f->body ! 1977: && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1978: f->dcl(p); ! 1979: p->simpl(); ! 1980: if (debug_opt) p->dcl_print(0); ! 1981: } ! 1982: break; ! 1983: case OVERLOAD: ! 1984: { Pgen g = Pgen(f); ! 1985: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 1986: Pname n = gl->f; ! 1987: Pfct f = Pfct(n->tp); ! 1988: ! 1989: if (f->body ! 1990: && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1991: f->dcl(n); ! 1992: n->simpl(); ! 1993: if (debug_opt) p->dcl_print(0); ! 1994: } ! 1995: } ! 1996: } ! 1997: } ! 1998: } ! 1999: ! 2000: if (tbl != gtbl) this->simpl(); ! 2001: ! 2002: extern Pname statStat; ! 2003: if ( statStat && strcmp(statStat->string,string)==0) { ! 2004: //error('d', "classdef::dcl: statstat: %n this %s", statStat, string); ! 2005: statStat->hide(); ! 2006: statStat = 0; ! 2007: } ! 2008: //error('d',"classdef::dcl -> %d",this); ! 2009: } ! 2010: ! 2011: void enumdef::dcl(Pname n, Ptable tbl) ! 2012: { ! 2013: // if (this == 0) error('i',"0->enumdef::dcl(%p)",tbl); ! 2014: Pname px; ! 2015: Pname p = mem; ! 2016: // error('d',"enumdef(%n,%d)",n,tbl); ! 2017: Pbase b = new basetype(EOBJ,n); ! 2018: b->b_const = 1; ! 2019: ! 2020: #define FIRST_ENUM 0 ! 2021: int enum_count = FIRST_ENUM; ! 2022: no_of_enumerators = mem->no_of_names(); ! 2023: int largest = 0; ! 2024: ! 2025: if (p == 0) mem = new name(make_name('e')); ! 2026: ! 2027: for (; p; p=px) { ! 2028: px = p->n_list; ! 2029: // error( 'd', "p %n", p ); ! 2030: if (p->n_initializer) { ! 2031: Pexpr i = p->n_initializer->typ(tbl); ! 2032: Neval = 0; ! 2033: long ii = i->eval(); ! 2034: if (largest_int<ii) error("long enumerator"); ! 2035: enum_count = int(ii); ! 2036: if (Neval) error("%s",Neval); ! 2037: DEL(i); ! 2038: p->n_initializer = 0; ! 2039: } ! 2040: p->n_evaluated = 1; ! 2041: largest |= enum_count; ! 2042: p->n_val = enum_count++; ! 2043: p->tp = b; ! 2044: ! 2045: Pname nn = tbl->insert(p,0); ! 2046: if (Nold) { ! 2047: if (nn->n_stclass == ENUM) { ! 2048: // error( (p->n_val!=nn->n_val)?0:'w',"enumerator%n declared twice",nn); ! 2049: // if (p->n_val!=nn->n_val) ! 2050: error("enumerator%n declared twice",nn); ! 2051: ! 2052: } ! 2053: else ! 2054: error("incompatibleDs of%n",nn); ! 2055: } ! 2056: else { ! 2057: nn->n_stclass = ENUM; // no store will be allocated ! 2058: if (Eppp == PROTECTED) ! 2059: nn->n_protect = PROTECTED; ! 2060: else if (Eppp == PUBLIC) ! 2061: nn->n_scope = PUBLIC; ! 2062: } ! 2063: p->string = nn->string; ! 2064: // delete p; ! 2065: } ! 2066: ! 2067: // mem = 0; ! 2068: ! 2069: // chose a shorter representation for the enum? ! 2070: // if (largest&0133 == largest) ! 2071: // e_type = char_type; ! 2072: // else if largest&077777 == largest) ! 2073: // e_type = short_type; ! 2074: // else ! 2075: e_type = int_type; ! 2076: ! 2077: defined |= DEFINED; ! 2078: } ! 2079:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.