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