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