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