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