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