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