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