|
|
1.1 root 1: /*ident "@(#)ctrans:src/dcl3.c 1.6.5.29" */
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: dcl3.c:
11: Routines used by ::dcl fucntions: fct::dcl() etc.
12:
13: *****************************************************************************/
14:
15: #include "cfront.h"
16: #include "size.h"
17: #include "template.h"
18:
19: extern loc no_where;
20: static void vbase_pointers(Pname fn, Pclass cl)
21: /*
22: insert argument for virtual base pointers (if any)
23: after f_this and before f_argtype
24: */
25: {
26: //error('d',"vbase_pointers(%n,%t) %d %k",fn,cl,fn->tp,fn->n_oper);
27: Pfct f = Pfct(fn->tp);
28: if (fn->n_oper == CTOR) {
29: Pname d = 0;
30: for (Pbcl b = cl->baselist; b; b=b->next) {
31: if (b->base != VIRTUAL) continue;
32: Pname a = new name(b->bclass->string);
33: a->tp = b->bclass->this_type;
34: a->n_list = d;
35: a->n_table = f->body ? f->body->memtbl : 0;
36: a->where = no_where;
37: d = a;
38: }
39:
40: if (d) {
41: for (Pname dd =d;;) {
42: if (d->n_list == 0) {
43: d->n_list = f->f_args->n_list;
44: break;
45: }
46: d = d->n_list;
47: }
48: f->f_args->n_list = dd;
49: }
50: }
51: if (fn->n_oper == DTOR) { // add __free argument
52: //error('d',"add __free to %n",fn);
53: Pname fa = new name;
54: fa->tp = int_type;
55: fa->n_scope = ARG;
56: fa->where = no_where;
57:
58: Pname a = f->f_args;
59: if (a == 0)
60: f->f_args = fa;
61: else {
62: for(;;a = a->n_list) {
63: // error('d',"a %d %t",a,a->tp);
64: if (a->n_list == 0) {
65: a->n_list = fa;
66: break;
67: }
68: }
69: }
70: }
71: }
72:
73: void make_res(Pfct f)
74: /*
75: returns X where X(X&) has been declared
76: add "_result" argument of type X*
77: */
78: {
79: Pname cl = f->returns->is_cl_obj();
80: if (cl==0 || Pclass(cl->tp)->has_itor()==0) return;
81:
82: Pname rv = new name("_result");
83: rv->tp = f->returns->addrof();
84: rv->n_scope = FCT; // not a ``real'' argument
85: rv->n_used = 1;
86: rv->n_list = f->argtype;
87: if (f->f_this)
88: f->f_this->n_list = rv;
89: else
90: f->f_args = rv;
91: f->f_result = rv;
92: f->s_returns = void_type;
93: }
94:
95: void name::check_oper(Pname cn)
96: /*
97: check declarations of operators, ctors, dtors
98: */
99: {
100: switch (n_oper) {
101: case CALL:
102: case DEREF:
103: case REF:
104: if (cn == 0) error("operator%s must be aM",keys[n_oper]);
105: break;
106: // case ASPLUS:
107: // case ASMINUS:
108: // case ASMUL:
109: // case ASDIV:
110: // case ASMOD:
111: // case ASAND:
112: // case ASOR:
113: // case ASER:
114: // case ASLS:
115: // case ASRS:
116: case ASSIGN:
117: if (cn == 0) error('w',"operator%k() must be aM (thisD will soon cease to compile)",n_oper);
118: break;
119: case 0:
120: case TNAME: /* may be a constructor */
121: if (cn &&
122: ((strcmp(cn->string,string)==0) ||
123: ((Pclass(cn->tp)->class_base == instantiated_template_class)&&
124: (strcmp(string,
125: Ptclass(cn->tp)->unparametrized_tname()->string)
126: == 0))))
127:
128: {
129: if (tp->base == FCT) {
130: Pfct f = Pfct(tp);
131: if (f->returns!=defa_type)
132: error("%s::%s()W returnT",string,string);
133: f->returns = void_type;
134: string = "__ct";
135: n_oper = CTOR;
136: }
137: else
138: error('s',"struct%nM%n",cn,cn);
139: }
140: else
141: n_oper = 0;
142: break;
143: case DTOR: /* must be a destructor */
144: //error('d',"dtor %s",string);
145: if (cn == 0) {
146: n_oper = 0;
147: error("destructor ~%s() not inC",string);
148: }
149: else if ((strcmp(cn->string,string) == 0) ||
150: ((Pclass(cn->tp)->class_base ==
151: instantiated_template_class) &&
152: (strcmp(string,
153: Ptclass(cn->tp)->unparametrized_tname()->string)
154: == 0))){
155: dto:
156: Pfct f = (Pfct)tp;
157: string = "__dt";
158: if (tp->base != FCT) {
159: error("%s::~%s notF",cn->string,cn->string);
160: tp = new fct(void_type,0,1);
161: }
162: else if (f->returns!=defa_type/* && f->returns!=void_type*/)
163: error("%s::~%s()W returnT",cn->string,cn->string);
164: if (f->argtype) {
165: error("%s::~%s()WAs",cn->string,cn->string);
166: f->nargs = 0;
167: f->nargs_known = 1;
168: f->argtype = 0;
169: }
170: f->returns = void_type;
171: }
172: else {
173: if (strcmp(string,"__dt") == 0) goto dto;
174: error("~%s in %s",string,cn->string);
175: n_oper = 0;
176: }
177: break;
178: case TYPE:
179: //error('d',"type %t",n_initializer);
180: if (cn == 0) {
181: error("operator%t() not aM",Ptype(n_initializer));
182: n_oper = 0;
183: n_initializer = 0;
184: }
185: else {
186: Pfct f = Pfct(tp);
187: Ptype tx = Ptype(n_initializer);
188: n_initializer = 0;
189: if (f->base != FCT) error("badT for%n::operator%t()",cn,tx);
190: if (f->returns != defa_type) {
191: // if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx);
192: error("resultT for%n::operator%t()",cn,tx);
193: DEL(f->returns);
194: }
195: if (f->argtype) {
196: error("%n::operator%t()WAs",cn,tx);
197: f->argtype = 0;
198: }
199: f->returns = tx;
200: Pname nx = tx->is_cl_obj();
201: if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx);
202: char buf[1024];
203: char* bb = tx->signature(buf);
204: int l2 = bb-buf;
205: if (1023<l2) error('i',"N::check_oper():N buffer overflow");
206: char* p = new char[l2+5];
207: p[0] = '_';
208: p[1] = '_';
209: p[2] = 'o';
210: p[3] = 'p';
211: strcpy(p+4,buf);
212: string = p;
213: }
214: break;
215: }
216: }
217:
218: Pexpr vbase_args(Pfct a, Pname bn)
219: /*
220: constructor a calls the constructor bn for a base class
221: generate argument list needed for virtual base arguments
222: */
223: {
224: Pfct b = Pfct(bn->tp);
225: //error('d',"vbase_args%n: %t %k",bn,b,b->base);
226: Pexpr args = 0;
227: Pexpr tail = 0;
228: if (b->base == OVERLOAD) b = Pfct(Pgen(b)->fct_list->f->tp); // doesn't matter which
229: for (Pname d = b->f_args->n_list; d!=b->argtype; d=d->n_list) {
230: for (Pname dd = a->f_args->n_list; dd; dd=dd->n_list)
231: // using strcmp is a trick
232: if (strcmp(dd->string,d->string)==0) break;
233:
234: Pexpr aa = new expr(ELIST,dd,0);
235: if (args == 0)
236: args = aa;
237: else
238: tail->e2 = aa;
239: tail = aa;
240: }
241: return args;
242: }
243:
244: void fct::init_bases(Pclass cl, Pexpr)
245: /*
246: in "cl"'s constructor "this" generate code to initialize base classes
247: and members using the initializers "f->f_init"
248:
249: this->f_init == list of names of classes to be initialized
250: COLON(b) => base class b
251: => constructor call in f_init->n_initializer
252: COLON() => unnamed base class
253: => constructor call in f_init->n_initializer
254: NAME(m) => member m
255: => constructor call in m->n_initializer
256: */
257: {
258: Ptable ftbl = body->memtbl;
259: //error('d',"init_bases %t init %d",cl,f_init);
260:
261: // explicit initializers
262: for (Pname nx, nn=f_init; nn; delete nn,(nn=nx) ) {
263: Pexpr i = nn->n_initializer;
264: nn->n_initializer = 0;
265: nx = nn->n_list;
266:
267: //error('d',"init_base %s %d",nn->string,i);
268: if (nn->string) {
269: if (nn->base == TNAME) { // base class
270: for (Pbcl l = cl->baselist; l; l=l->next) {
271: Pclass bcl = l->bclass;
272: if ((strcmp(bcl->string,nn->string) == 0) ||
273: ((bcl->class_base ==
274: instantiated_template_class) &&
275: ((strcmp(
276: Ptclass(bcl)->unparametrized_tname()->string, nn->string)) == 0)))
277:
278: {
279: if (l->init)
280: error("twoIrs for%t",bcl);
281: else
282: l->init = base_init(bcl,i,ftbl,l->obj_offset);
283: goto con;
284: }
285: }
286: error("unexpectedAL: noBC%n",nn);
287: con:
288: continue;
289: }
290: else { // member initializer
291: Pname m = cl->memtbl->look(nn->string,0);
292: if (m && m->n_table==cl->memtbl)
293: m->n_initializer = mem_init(m,i,ftbl);
294: else
295: error("%n not inC%n",m,nn);
296: }
297: }
298: else { // unnamed base class
299: Pbcl l = cl->baselist;
300: if (l == 0) {
301: error("unexpectedAL: noBC called");
302: continue;
303: }
304:
305: if (l->next) {
306: error("unnamedBCIr: multipleBCs");
307: continue;
308: }
309:
310: if (l->init)
311: error("twoIrs for%t",l->bclass);
312: else {
313: if (strict_opt) error("anachronism:N ofBC %t missing",l->bclass);
314: l->init = base_init(l->bclass,i,ftbl,l->obj_offset);
315: }
316: }
317: } // for
318:
319: for (Pbcl l = cl->baselist; l; l=l->next) {
320: // default initialization of base classes
321: Pname ctor;
322: Pclass bcl = l->bclass;
323: if (l->init==0 && (ctor=bcl->has_ctor()))
324: l->init = base_init(bcl,0,ftbl,l->obj_offset);
325: }
326: }
327:
328: int inline_restr; /* report use of constructs that the inline expanded
329: cannot handle here
330: */
331:
332: void fct::dcl(Pname n)
333: {
334: int nmem = TBLSIZE;
335: Pname a;
336: Pname ll;
337: Ptable ftbl;
338:
339: Pptr cct = 0;
340: int const_old = const_save;
341:
342: int bit_old = bit_offset;
343: int byte_old = byte_offset;
344: int max_old = max_align;
345:
346: if (base != FCT) error('i',"F::dcl(%d)",base);
347: if (body == 0) error('i',"F::dcl(body=%d)",body);
348: if (n==0 || n->base!=NAME) error('i',"F::dcl(N=%d %d)",n,(n)?n->base:0);
349: //error('d',"fct::dcl(%n) %k %d %t",n,n->n_scope,body->own_tbl,this);
350: if (body->own_tbl) return; // done already
351:
352: // if (f_inline==0 /*|| debug_opt*/) n->n_dcl_printed = 1; // beware of recursive calls, no decl needed
353: // if (f_inline && debug_opt) n->n_dcl_printed = 2;
354: if (body->memtbl == 0) body->memtbl = new table(nmem+3,gtbl,0);
355: body->own_tbl = 1;
356: ftbl = body->memtbl;
357: ftbl->real_block = body;
358:
359: max_align = 0;//AL_FRAME;
360: bit_offset = 0;
361:
362: cc->stack();
363: cc->nof = n;
364: cc->ftbl = ftbl;
365:
366: switch (n->n_scope) {
367: case 0:
368: case PUBLIC:
369: { cc->not = n->n_table->t_name;
370: cc->cot = Pclass(cc->not->tp);
371: cc->tot = cc->cot->this_type;
372: // if (f_this==0 || cc->tot==0) error('i',"F::dcl(%n): f_this=%d cc->tot=%d",n,f_this,cc->tot);
373: if (f_this) f_this->n_table = ftbl; // fake for inline printout
374: cc->c_this = f_this;
375:
376:
377: Pclass cl = Pclass(cc->not->tp);
378:
379: if (cl->c_body!=3
380: || n->n_initializer
381: || n->n_sto==STATIC
382: || f_inline
383: || f_imeasure
384: || f_virtual==0)
385: ;
386: else { // could be the function where we need to
387: // output the vtbl
388: int i;
389: for (Pname nn=cl->memtbl->get_mem(i=1); nn; nn=cl->memtbl->get_mem(++i) ) {
390: Ptype t = nn->tp;
391: if (t)
392: switch (t->base) {
393: case FCT:
394: if (nn == n) goto prnt;
395: if (nn->n_initializer
396: || nn->n_sto==STATIC
397: || Pfct(nn->tp)->f_inline
398: || Pfct(nn->tp)->f_imeasure
399: || Pfct(nn->tp)->f_virtual==0) break;
400: goto zaq;
401:
402: case OVERLOAD:
403: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
404: Pname nn = gl->f;
405: if (nn == n) goto prnt;
406: if (nn->n_initializer
407: || nn->n_sto==STATIC
408: || Pfct(nn->tp)->f_inline
409: || Pfct(nn->tp)->f_imeasure
410: || Pfct(nn->tp)->f_virtual==0) continue;
411: goto zaq;
412: }
413: }
414: }
415: }
416: goto zaq;
417: prnt:
418: cl->print_all_vtbls(cl);
419: goto zaq;
420: }
421: }
422: }
423: zaq:
424: // protect against: class x; x f(); class x { x(x&); ....
425: if (f_result == 0) make_res(this);
426: if (f_result) f_result->n_table = ftbl; // fake for inline printout
427:
428: returns->tsizeof(); // make sure size is known
429:
430: Pname ax;
431: for (a=argtype, ll=0; a; a=ax) {
432: ax = a->n_list;
433: Pname nn = a->dcl(ftbl,ARG);
434: Pname cn = nn->tp->is_cl_obj();
435: if (cn == 0) cn = cl_obj_vec;
436: if (cn) (void)cn->tp->tsizeof(); // make sure it is printed
437: nn->n_assigned_to = nn->n_used = nn->n_addr_taken = 0;
438: nn->n_list = 0;
439:
440: switch (nn->tp->base) {
441: case CLASS:
442: case ENUM: /* unlink types declared in arg list */
443: nn->dcl_print(0);
444: break;
445: default:
446: if (ll)
447: ll->n_list = nn;
448: else
449: f_args = argtype = nn;
450: ll = nn;
451: }
452: delete a;
453: }
454:
455: if (f_result) { // link in f_result
456: f_args = f_result;
457: f_result->n_list = argtype;
458: }
459:
460: if (f_this) { // link in f_this
461: f_args = f_this;
462: f_this->n_list = f_result ? f_result : argtype;
463: }
464:
465: if (n->n_oper==CTOR || n->n_oper==DTOR) vbase_pointers(n,cc->cot);
466:
467: if (n->n_oper == CTOR) {
468: const_save = 1;
469: init_bases(cc->cot,f_init);
470: }
471: else if (f_init)
472: error(0,"unexpectedAL: not aK");
473:
474: PERM(returns);
475: const_save = f_inline&&debug_opt==0;
476: inline_restr = 0;
477: body->dcl(ftbl);
478:
479: defined |= DEFINED;
480: if (f_inline && inline_restr && returns->base!=VOID) {
481: f_inline = 0;
482: char* s = (inline_restr & 32) ? "continue"
483: : (inline_restr & 16) ? "break"
484: : (inline_restr & 8) ? "loop"
485: : (inline_restr & 4) ? "switch"
486: : (inline_restr & 2) ? "goto"
487: : (inline_restr & 1) ? "label"
488: : "" ;
489: error('w', "\"inline\" ignored, %n contains %s",n,s);
490: // if (cc->cot)
491: n->simpl(); //BS6
492: n->dcl_print(0);
493: }
494: const_save = const_old;
495:
496: if (f_inline && debug_opt==0) isf_list = new name_list(n,isf_list);
497:
498: bit_offset = bit_old;
499: byte_offset = byte_old;
500: max_align = max_old;
501: cc->unstack();
502: //error('d',"fct-> returns %t",returns);
503: }
504:
505: Pexpr fct::base_init(Pclass bcl, Pexpr i, Ptable ftbl, int offset)
506: /*
507: have base class bcl and expr list i
508: return "( *(base*)this ) . ctor( i )"
509: ctor call generated in expr.typ()
510: */
511: {
512: Ptype ty = bcl->this_type;
513: Pexpr th = rptr(ty,f_this,offset); // base*
514: Pname ctor = bcl->has_ctor();
515:
516: //error('d',"fct::B_init(C %t, i %d, %d) ctor %n",bcl,i,i?i->tp:0,ctor);
517:
518: Pexpr ii = (i && i->base==ELIST)?i->e1:i;
519:
520: if (ii
521: && ii->base==DEREF
522: && ii->e1->base==CAST
523: && th->base==CAST) th->i2 = ii->e1->i2;
524:
525: if (ctor == 0) {
526: if (i && i->base!=ELIST) i = new expr(ELIST,i,0);
527:
528: Pexpr v = new texpr(VALUE,bcl,i); // ?.base(i)
529: v->e2 = new expr(DEREF,th,0); // (*(base*)this).base(i)
530: v = v->typ(ftbl); // *base(&*(base*)this,i)
531: //error('d',"v %k",v->base);
532: switch (v->base) {
533: case DEREF:
534: return v->e1; // base(&*(base*)this,i)
535: case ASSIGN: // degenerate base(base&): *(base*)this=i
536: th = new texpr(CAST,ty,f_this);
537: v = new expr(CM,v,th); // (*(base*)this=i,(base*)this);
538: return v->typ(ftbl);
539: default:
540: return 0;
541: }
542: }
543:
544:
545: Pname icn;
546: if (i) {
547: ii = ii->typ(ftbl);
548: if (bcl->has_itor()==0
549: && (icn=ii->tp->is_cl_obj())
550: && (Pclass(icn->tp)==bcl || Pclass(icn->tp)->has_base(bcl))) {
551: // degenerate base(base&): *(base*)this=i
552: // memberwise copy
553: //error('d',"copy %t",ty);
554: // th = new cast(ty,f_this);
555: // th = th->contents();
556: th = new texpr(CAST,ty,f_this);
557: th = th->contents();
558: th = th->typ(ftbl);
559: if (Pclass(icn->tp)!=bcl) { // cast needed
560: Pptr r = new ptr(RPTR,Pptr(ty)->typ);
561: ii = new texpr(CAST,r,ii);
562: ii = ii->typ(ftbl);
563: }
564: ii = new expr(ASSIGN,th,ii);
565: ii->tp = th->tp;
566: // simulate `return this':
567: // *(base*)this=i,(base*)this
568: ii = new expr(CM,ii,new cast(ty,f_this));
569: ii->tp = th->tp;
570: return ii;
571: // return ii->typ(ftbl); // don't find cl::operator=()
572: }
573: if (i->base == ELIST) i->e1 = ii;
574: }
575: //Pexpr x = call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
576: //error('d',"call %n %t -> %d %k",ctor,ctor->tp,x,x->base);
577: // return x;
578: return call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
579: }
580:
581:
582: Pexpr fct::mem_init(Pname mn, Pexpr i, Ptable ftbl)
583: /*
584: return "member_ctor( m, i )"
585: */
586: {
587: // a new entry for B::B_pub, in general, has no tp and no
588: // real info: all the tp-> only work on our systems because
589: // 0 pointer dereference isn't system memory. it core dumps
590: // in set_const since no test is made on this == 0.
591: //error('d',"mem_init %n",mn);
592:
593: // if (mn->n_stclass == STATIC) error('s',"MIr for static%n",mn);
594: switch (mn->n_stclass) {
595: case STATIC:
596: error("MIr for static%n",mn);
597: break;
598: case ENUM:
599: error("MIr for enumeration constant%n", mn);
600: break;
601: }
602:
603: Pname member = (mn->base==PUBLIC && mn->n_qualifier) ? mn->n_qualifier : mn;
604:
605: if (i) i = i->typ(ftbl);
606: Pname cn = member->tp->is_cl_obj(); // first find the class name
607:
608: // if (member->n_stclass == STATIC) error('s',"MIr for static%n",member);
609: // if (i) i = i->typ(ftbl);
610: // Pname cn = member->tp->is_cl_obj(); // first find the class name
611: Pref tn = new ref(REF,f_this,member);
612: tn->tp = member->tp;
613: //error('d',"MI for %n %t = %t",member,member->tp,i?i->tp:0);
614: //error('d',"fthis %d %t member %n tp %t",f_this,f_this->tp,member,tn->tp);
615: if (cn) {
616: Pclass mcl = Pclass(cn->tp); // then find the classdef
617: Pname ctor = mcl->has_ctor();
618: Pname icn;
619:
620: if (i
621: && mcl->has_itor()==0
622: && (icn=i->tp->is_cl_obj())
623: && Pclass(icn->tp)==mcl) { // bitwise copy
624: Pexpr init = new expr(ASSIGN,tn,i);
625: init->tp = tn->tp;
626: // return init->typ(ftbl); // don't look for mcl.operator=()
627: member->assign();
628: return init;
629: }
630:
631: if (ctor) return call_ctor(ftbl,tn,ctor,i,DOT);
632:
633: error("Ir forM%nW noK",member);
634: return 0;
635: }
636:
637: if (cl_obj_vec) {
638: error('s',"Ir forCM arrayWK");
639: return 0;
640: }
641:
642: if (i && i->base == ELIST) {
643: // if (i->base == ELIST) {
644: if (i->e2) error("Ir for%n not a simpleE",member);
645: i = i->e1;
646: }
647:
648:
649: // error( 'd', "fct_mem_init: %n %k", member, member->tp->base );
650:
651: if (member->tp->is_ref() && ( i == 0 )) {
652: error( "empty Ir for reference %n", member ) ;
653: return 0 ;
654: }
655: switch (member->tp->base) {
656: /* Sam: this test is inadequate, since an RPTR can hide behind a */
657: /* TNAME the new test above is the correct one */
658: /*
659: case RPTR:
660: if ( i == 0 ) {
661: error( "empty Ir for reference %n", member );
662: return 0;
663: }
664: break;
665: */
666: case VEC:
667: case FCT:
668: case OVERLOAD:
669: error("Ir for%n ofT %t",member,member->tp);
670: return 0;
671: }
672:
673: //error('d',"tp %t",member->tp);
674: if (member->tp->tconst()) {
675: extern ignore_const;
676: int save_ignore_const = ignore_const;
677: ignore_const = 1;
678: i = new expr(ASSIGN,tn,i);
679: i = i->typ(ftbl);
680: ignore_const = save_ignore_const;
681: return i;
682: }
683:
684: Pptr pt;
685: if (pt = member->tp->is_ref()) {
686: switch (pt->typ->base) {
687: case FCT:
688: case OVERLOAD:
689: i = ptr_init(pt,i,ftbl);
690: break;
691: default:
692: i = ref_init(pt,i,ftbl);
693: }
694: i = new expr(ASSIGN,tn,i);
695: i->tp = tn->tp;
696: member->assign(); // cannot call typ: would cause dereference
697: return i;
698: }
699:
700: i = new expr(ASSIGN,tn,i);
701: return i->typ(ftbl); // typ performs the type check on the assignment
702: }
703:
704: Pexpr replace_temp(Pexpr e, Pexpr n)
705: /*
706: e is on the form
707: f(&temp,arg) , temp
708: or
709: &temp->ctor(arg) , temp
710: or
711: x->f(&temp,arg) , temp
712: change it to
713: f(n,arg)
714: or
715: n->ctor(arg)
716: */
717: {
718: Pexpr c = e->e1; // f(&temp,arg) or &temp->ctor(args)
719: Pexpr ff = c->e1;
720: Pexpr a = c->e2; // maybe ELIST(&temp,arg)
721: Pexpr tmp = e->e2;
722:
723: //error('d',"suppress(%d %k) %n",tmp->base,tmp->base,tmp->base==NAME?tmp:0);
724: if (tmp->base==DEREF) tmp = tmp->e1;
725: if (tmp->base==CAST) tmp = tmp->e1;
726: if (tmp->base==ADDROF || tmp->base==G_ADDROF) tmp = tmp->e2;
727: if (tmp->base != NAME) return e; //error('i',"replace %k",tmp->base);
728: tmp->tp = any_type; // temporary not used: suppress it
729:
730: //error('d',"replace_temp(%k %k) c %k ff %k",e->base,n->base,c->base,ff->base);
731: switch (ff->base) {
732: case REF:
733: if (ff->e1->base==G_ADDROF && ff->e1->e2==tmp)
734: a = ff; // &tmp -> f()
735: break;
736: case DOT:
737: if (ff->e1->base==NAME && ff->e1==tmp) {
738: a = ff; // tmp . f()
739: a->base = REF;
740: }
741: break;
742: }
743: a->e1 = n;
744: return c;
745: }
746:
747: Pname classdef::has_ictor()
748: /*
749: does this class have a constructor taking no arguments?
750: */
751: {
752: Pname c = has_ctor();
753: if (c == 0) return 0;
754:
755: Pfct f = Pfct(c->tp);
756:
757: switch (f->base) {
758: default:
759: error('i',"%s: badK (%k)",string,c->tp->base);
760:
761: case FCT:
762: switch (f->nargs) {
763: case 0: return c;
764: default: if (f->argtype->n_initializer) return c;
765: }
766: return 0;
767:
768: case OVERLOAD:
769: { for (Plist l=Pgen(f)->fct_list; l; l=l->l) {
770: Pname n = l->f;
771: f = (Pfct)n->tp;
772: switch (f->nargs) {
773: case 0: return n;
774: default: if (f->argtype->n_initializer) return n;
775: }
776: }
777: return 0;
778: }
779: }
780: }
781:
782: int add_first; // fudge, use ctor arg instead
783: Pname gen::add(Pname n)
784: /*
785: add "n" to the tail of "fct_list"
786: (overloaded names are searched in declaration order)
787:
788: detect: multiple identical declarations
789: declaration after use
790: multiple definitions
791: */
792: {
793: extern linkage;
794: Pfct f = Pfct(n->tp);
795: Pname nx;
796: //error('d',"add(%n) %d",n,add_first);
797: if (f->base != FCT) error("%n: overloaded nonF",n);
798:
799: if ( fct_list && (nx=find(f,1)) ) {
800: //error('d',"found %n %t",nx,nx->tp);
801: if (linkage && Pfct(nx->tp)->f_signature && Pfct(nx->tp)->f_signature[0])
802: error("inconsistent linkage specifications for%n",n);
803: Nold = 1;
804: }
805: else {
806: //extern linkage;
807: if (add_first==0)
808: if (linkage==0 && f->f_signature==0) f->sign();
809: //error('d',"signature: %d \"%s\" fct_list %d",f->f_signature,f->f_signature,fct_list);
810: nx = new name;
811: *nx = *n;
812: nx->n_gen_fct_name = n->string;
813: PERM(nx);
814: Nold = 0;
815: if (fct_list) {
816: int clink = f->f_signature==0 || *f->f_signature==0; // function with C linkage
817: Plist gl=fct_list;
818: for(;;) {
819: if (clink
820: && (Pfct(gl->f->tp)->f_signature==0
821: || *Pfct(gl->f->tp)->f_signature==0)) {
822: error("two%ns with c linkage",n);
823: f->sign();
824: }
825: if (gl->l)
826: gl = gl->l;
827: else
828: break;
829: }
830: gl->l = new name_list(nx,0);
831: }
832: else
833: fct_list = new name_list(nx,0);
834: nx->n_list = 0;
835: }
836: return nx;
837: }
838:
839: void fct::sign()
840: {
841: char buf[1024];
842: char* bb = signature(buf);
843: int ll = bb-buf;
844: if (1023 < ll) error('i',"gen::add():N buffer overflow");
845: char* p = new char[ll+1];
846: strcpy(p,buf);
847: f_signature = p;
848: //error('d',"fct::sign %s",p);
849: }
850:
851: Pname gen::find(Pfct f, bit warn)
852: {
853: for (Plist gl=fct_list; gl; gl=gl->l) {
854: Pname n = match(gl->f,f,warn);
855: if (n) return n;
856: }
857: return 0;
858: }
859:
860: Pname gen::match(Pname nx, Pfct f, bit warn)
861: {
862: Pfct fx = Pfct(nx->tp);
863: Pname a, ax;
864: int op = 0; // overloading problem: const, ref, vec/ptr, or basetype
865: //error('d',"fx %d %d f %d %d",fx->nargs_known,fx->nargs,f->nargs_known,f->nargs);
866:
867: if (f->nargs_known != fx->nargs_known) return 0; // the bets are off
868: // must rely on checks at
869: // call points
870: if (f->f_const != fx->f_const) return 0;
871:
872: if (fx->nargs != f->nargs
873: && fx->nargs_known==1
874: && f->nargs_known==1) return 0; // no warning for potential
875: // problems due to default args
876:
877: for (ax=fx->argtype, a=f->argtype; a&&ax; ax=ax->n_list, a=a->n_list) {
878: Ptype at = ax->tp;
879: Ptype atp = a->tp;
880: //error('d',"at %t atp %t",at,atp);
881: if (at->check(atp,OVERLOAD) == 0) {
882: //error('d',"at %t atp %t cp %d vrp %d",at,atp,const_problem,vrp_equiv);
883: // if (vrp_equiv) op++; // or differ only by [] vs *
884: continue;
885: }
886: //error('d',"warn %d",warn);
887: if (warn == 0) goto xx;
888:
889: /*
890: warn against:
891: overload f(X&), f(X); error
892: overload f(int), f(const); error
893: overload f(int*), f(int[10]); warn
894: etc.
895: */
896:
897: //error('d',"vrp_equiv %d const_problem %d",vrp_equiv,const_problem);
898: if (const_problem) { // differ only in X vs const X
899: if (at->is_ptr_or_ref()) return 0;
900: op++;
901: continue;
902: }
903:
904: aaa:
905: switch (atp->base) {
906: case TYPE:
907: atp = Pbase(atp)->b_name->tp;
908: goto aaa;
909: // case EOBJ:
910: // atp = Penum(Pbase(atp)->b_name->tp)->e_type;
911: // goto aaa;
912: case RPTR: // differ only by X vs X& ?
913: if (Pptr(atp)->typ->check(at,0)==0) {
914: op++;
915: continue;
916: }
917: }
918:
919: atl:
920: switch (at->base) {
921: case TYPE:
922: at = Pbase(at)->b_name->tp;
923: goto atl;
924: // case EOBJ:
925: // at = Penum(Pbase(at)->b_name->tp)->e_type;
926: // goto atl;
927: case RPTR: // differ only by X& vs X ?
928: if (Pptr(at)->typ->check(atp,0)==0) {
929: op++;
930: continue;
931: }
932: break;
933: // case CHAR: // differ only by int vs char ?
934: // case SHORT:
935: // case INT:
936: // if (atp->base!=at->base && atp->base==EOBJ) {
937: // op++;
938: // continue;
939: // }
940: // break;
941: }
942: //error('d',"return 0");
943: //goto xx;
944: // some argument is really different
945: // e.g. f(int), f(char*);
946: return 0;
947: }
948:
949: // arguments checked. Now look at leftover args, return type,etc.
950:
951: // if (warn && a && fx->nargs_known==ELLIPSIS) error('w',"... in%n'sAT hidesATs from the overloading mechanism",nx);
952:
953: if (a || ax) return 0;
954:
955: if (op == 0) {
956: if (warn && fx->returns->check(f->returns,0))
957: error("two different return valueTs for%n: %t and %t",nx,fx->returns,f->returns);
958:
959: return nx;
960: }
961: xx:
962: if (warn && op)
963: error("the overloading mechanism cannot tell a%t from a%t",fx,f);
964:
965: return 0;
966: }
967:
968: int name::no_of_names()
969: {
970: register int i = 0;
971: register Pname n;
972: for (n=this; n; n=n->n_list) i++;
973: return i;
974: }
975:
976: static Pexpr lvec[20], *lll, *curr_e;
977: static Pexpr list_back = 0;
978:
979: void new_list(Pexpr lx)
980: {
981: if (lx->base != ILIST) error('i',"IrLX");
982:
983: lll = lvec;
984: lll++;
985: *lll = lx->e1;
986: }
987:
988: Pexpr next_elem()
989: {
990: Pexpr e;
991: Pexpr lx;
992:
993: if (lll == lvec) return 0;
994:
995: lx = *lll;
996:
997: if (list_back) {
998: e = list_back;
999: list_back = 0;
1000: return e;
1001: }
1002:
1003: if (lx == 0) { /* end of list */
1004: lll--;
1005: return 0;
1006: }
1007:
1008: switch (lx->base) {
1009: case ELIST:
1010: e = lx->e1;
1011: curr_e = &lx->e1;
1012: *lll = lx->e2;
1013: switch (e->base) {
1014: case ILIST:
1015: lll++;
1016: *lll = e->e1;
1017: return Pexpr(1); // start of new ILIST
1018: case ELIST:
1019: error("nestedEL");
1020: return 0;
1021: default:
1022: {
1023: int need_sti(Pexpr, Ptable tbl = 0);
1024: if (need_sti(e)) error('s',"generalIr inIrL");
1025: return e;
1026: }
1027: }
1028: case IVAL:
1029: case ZERO:
1030: lll--;
1031: return 0;
1032: default:
1033: error('i',"IrL %k",lx->base);
1034: }
1035: }
1036:
1037: void skip_ilist()
1038: // skip ilist use to represent pointer to member function literal
1039: {
1040: Pexpr e = next_elem();
1041: e = next_elem();
1042: }
1043:
1044: void list_check(Pname nn, Ptype t, Pexpr il)
1045: /*
1046: see if the list "lll" can be assigned to something of type "t"
1047: "nn" is the name of the variable for which the assignment is taking place.
1048: "il" is the last list element returned by next_elem()
1049: */
1050: {
1051: Pexpr e;
1052: bit lst = 0;
1053: int i;
1054: Pclass cl;
1055: int tdef = 0;
1056:
1057: //error('d',"list_check%n: %t (%d)",nn,t,il);
1058: if (il == Pexpr(1))
1059: lst = 1;
1060: else if (il)
1061: list_back = il;
1062:
1063: zzz:
1064: switch (t->base) {
1065: case TYPE:
1066: t = Pbase(t)->b_name->tp;
1067: tdef = 1;
1068: goto zzz;
1069:
1070: case VEC:
1071: { Pvec v = Pvec(t);
1072: Ptype vt = v->typ;
1073:
1074: if (v->size) { /* get at most v->size initializers */
1075: if (v->typ->base == CHAR) {
1076: e = next_elem();
1077: if (e->base == STRING) { // v[size] = "..."
1078: int isz = Pvec(e->tp)->size;
1079: if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size);
1080: break;
1081: }
1082: else
1083: list_back = e;
1084: }
1085: for (i=0; i<v->size; i++) { // check next list element type
1086: ee:
1087: e = next_elem();
1088: if (e == 0) goto xsw; // too few initializers are ok
1089: vtz:
1090: //error('d',"vtz: %d",vt->base);
1091: switch (vt->base) {
1092: case TYPE:
1093: vt = Pbase(vt)->b_name->tp;
1094: goto vtz;
1095: case VEC:
1096: case COBJ:
1097: list_check(nn,vt,e);
1098: break;
1099: case PTR:
1100: if (Pptr(vt)->memof
1101: && Pptr(vt)->typ->base==FCT
1102: && e==Pexpr(1)) {
1103: skip_ilist();
1104: break;
1105: }
1106: // no break
1107: default:
1108: {
1109: if (e == (Pexpr)1) {
1110: error("unexpectedIrL");
1111: goto ee;
1112: }
1113:
1114: if (vt->check(e->tp,ASSIGN))
1115: error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
1116:
1117: Pptr p;
1118: if (vt->check(e->tp,0)
1119: && (p=vt->is_ptr())
1120: && Ptype(p)!=zero_type
1121: && p->typ!=char_type)
1122: *curr_e = new cast(vt,e);
1123: }
1124: }
1125: }
1126: if ( lst && (e=next_elem()) ) error("end ofIrLX after array");
1127: xsw:;
1128: }
1129: else { /* determine v->size */
1130: i = 0;
1131: (void) v->typ->tsizeof();
1132: xx:
1133: while ( e=next_elem() ) { // get another initializer
1134: i++;
1135: vtzz:
1136: //error('d',"vtzz");
1137: switch (vt->base) {
1138: case TYPE:
1139: vt = Pbase(vt)->b_name->tp;
1140: goto vtzz;
1141: case VEC:
1142: case COBJ:
1143: list_check(nn,vt,e);
1144: break;
1145: case PTR:
1146: if (Pptr(vt)->memof
1147: && Pptr(vt)->typ->base==FCT
1148: && e==Pexpr(1)) {
1149: skip_ilist();
1150: break;
1151: }
1152: // no break
1153: default:
1154: { if (e == Pexpr(1)) {
1155: error("unexpectedIrL");
1156: goto xx;
1157: }
1158:
1159: if (vt->check(e->tp,ASSIGN))
1160: error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
1161:
1162: Pptr p;
1163: if (vt->check(e->tp,0)
1164: && (p=vt->is_ptr())
1165: && Ptype(p)!=zero_type
1166: && p->typ!=char_type)
1167: *curr_e = new cast(vt,e);
1168: }
1169: }
1170: }
1171: if (tdef==0) v->size = i;
1172: }
1173: break;
1174: }
1175:
1176: case CLASS:
1177: cl = Pclass(t);
1178: goto ccc;
1179:
1180: case COBJ: /* initialize members */
1181: cl = Pclass(Pbase(t)->b_name->tp);
1182: ccc:
1183: if (cl->defined == 0) {
1184: lll = lvec; // we are lost: ignore rest of list
1185: return;
1186: }
1187:
1188: if (cl->c_body == 1) cl->dcl_print(0);
1189:
1190: { Ptable tbl = cl->memtbl;
1191: Pname m;
1192:
1193: if (cl->baselist) {
1194: if (cl->baselist->next) error("IrL forO ofC with multipleBCs");
1195: list_check(nn,cl->baselist->bclass,0);
1196: }
1197:
1198: for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) {
1199: Ptype mt = m->tp;
1200: switch (mt->base) {
1201: case FCT:
1202: case OVERLOAD:
1203: case CLASS:
1204: case ENUM:
1205: continue;
1206: }
1207: if (m->n_stclass == STATIC) continue;
1208: /* check assignment to next member */
1209: dd:
1210: e = next_elem();
1211: if (e == 0) return; //break;
1212: mtz:
1213: //error('d',"mtz%n: %d",m,mt->base);
1214: switch (mt->base) {
1215: case TYPE:
1216: mt = Pbase(mt)->b_name->tp;
1217: goto mtz;
1218: case CLASS:
1219: case ENUM:
1220: break;
1221: case VEC:
1222: case COBJ:
1223: list_check(nn,m->tp,e);
1224: break;
1225: case PTR:
1226: if (Pptr(mt)->memof
1227: && Pptr(mt)->typ->base==FCT
1228: && e==Pexpr(1)) {
1229: skip_ilist();
1230: break;
1231: }
1232: // no break
1233: default:
1234: { if (e == Pexpr(1)) {
1235: error("unexpectedIrL");
1236: goto dd;
1237: }
1238:
1239: if (mt->check(e->tp,ASSIGN))
1240: error("badIrT for%n:%t (%tX)",m,e->tp,m->tp);
1241:
1242: Pptr p;
1243: if (mt->check(e->tp,0)
1244: && (p=mt->is_ptr())
1245: && Ptype(p)!=zero_type
1246: && p->typ!=char_type)
1247: *curr_e = new cast(mt,e);
1248: }
1249: }
1250: }
1251: if (lst && (e=next_elem()) ) error("end ofIrLX afterCO");
1252: break;
1253: }
1254: default:
1255: e = next_elem();
1256:
1257: if (e == 0) {
1258: error("noIr forO");
1259: break;
1260: }
1261:
1262: if (e == Pexpr(1)) {
1263: error("unexpectedIrL");
1264: break;
1265: }
1266: //error('d',"t %t e->tp %t",t,e->tp);
1267: if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t);
1268: Pptr p;
1269: if (t->check(e->tp,0)
1270: && (p=t->is_ptr())
1271: && Ptype(p)!=zero_type
1272: && p->typ!=char_type)
1273: *curr_e = new cast(t,e);
1274: if (lst && (e=next_elem()) ) error("end ofIrLX afterO");
1275: break;
1276: }
1277: }
1278:
1279: Pname dclass(Pname n, Ptable tbl)
1280: {
1281: Pclass cl;
1282: Pbase bt;
1283: Pname bn;
1284: TOK t;
1285:
1286: //local class
1287: Pname nx = ktbl->look(n->string,0); // TNAME
1288: // error( 'd', "dclass n %n %d nx %d", n,n->lex_level, nx);
1289: if (nx == 0 || n->lex_level ) {
1290: /* search for hidden name for
1291: (1) nested class declaration
1292: (2) local class declaration
1293: */
1294: int tn = 0;
1295: t = n->lex_level ? LOCAL : HIDDEN;
1296: // error( 'd', "dclass t: %k", t );
1297: for (nx=ktbl->look(n->string,t); nx; nx=nx->n_tbl_list) {
1298: // error('d',"dclass: %n %t t: %s",n,n->tp, t==LOCAL?"Local":"Hidden");
1299: // error('d',"dclass: nx: %s %k t: %s",nx->string,nx->tp->base, t==LOCAL?"Local":"Hidden");
1300: if (nx->n_key != t) continue;
1301: if ( nx->lex_level != n->lex_level ) continue;
1302:
1303: if (nx->tp->base != COBJ) {
1304: tn = 1;
1305: continue;
1306: }
1307:
1308:
1309: bt = (Pbase)nx->tp;
1310: bn = bt->b_name;
1311: cl = (Pclass)bn->tp;
1312:
1313: if (cl == 0) continue;
1314:
1315: if ( n->lex_level &&
1316: (cl->lcl==0 || strcmp(cl->lcl,Pclass(n->tp)->lcl))) continue;
1317: //error('d',"goto bbb");
1318: goto bbb;
1319: }
1320:
1321: if (tn)
1322: error("%n redefined using typedef",n);
1323: else
1324: error('i',"%n is not aCN",n);
1325: }
1326: else {
1327: bt = Pbase(nx->tp); // COBJ
1328: // error ('d', "dclass: bt->base: %k", bt->base );
1329: if ( bt->base != COBJ ) {
1330: error("%n redefined using typedef",n);
1331: Pname tn = ktbl->look(n->string,HIDDEN);
1332: // error( 'd', "dclass: tn: %t", tn );
1333: if ( tn->tp->base == COBJ )
1334: bt = Pbase(tn->tp);
1335: else error('i',"%n is not a CN", n );
1336: }
1337: bn = bt->b_name;
1338: }
1339: bbb:
1340: Pname ln = tbl->look(bn->string,0);
1341: // if (ln && ln->n_table==tbl) error('w',"%n redefined",ln);
1342: //error('d',"ln %n",ln);
1343: bn->where = nx->where;
1344: Pname bnn = tbl->insert(bn,CLASS); // copy for member lookup
1345: cl = Pclass(bn->tp);
1346: if (cl->class_base == template_class)
1347: error ("class %n was previously defined as a template class",
1348: bn) ;
1349: // CLASS
1350: if (cl->defined&(DEFINED|SIMPLIFIED))
1351: error("C%n defined twice",n);
1352: else {
1353: if (bn->n_scope == ARG) bn->n_scope = ARGT;
1354: cl->dcl(bn,tbl);
1355: }
1356: n->tp = cl;
1357: //error('d'," -> ");
1358: return bnn;
1359: }
1360:
1361: Pname denum(Pname n, Ptable tbl)
1362: {
1363: Pname nx = ktbl->look(n->string,0); // TNAME
1364: if (nx == 0) nx = ktbl->look(n->string,HIDDEN); // hidden TNAME
1365: Pbase bt = (Pbase)nx->tp; // EOBJ
1366: Pname bn = bt->b_name;
1367: Pname bnn = tbl->insert(bn,CLASS);
1368: Penum en = (Penum)bn->tp; // ENUM
1369: if (en->defined&(DEFINED|SIMPLIFIED))
1370: error("enum%n defined twice",n);
1371: else {
1372: if (bn->n_scope == ARG) bn->n_scope = ARGT;
1373: en->dcl(bn,tbl);
1374: }
1375: n->tp = en;
1376: return bnn;
1377: }
1378:
1379: void dargs(Pname, Pfct f, Ptable tbl)
1380: {
1381: int oo = const_save;
1382: const_save = 1;
1383:
1384: for (Pname a=f->argtype; a; a=a->n_list) {
1385: Pexpr init;
1386:
1387: if (a->tp == 0) {
1388: error( "A has noT" );
1389: a->tp = any_type;
1390: continue;
1391: }
1392:
1393: Pname cln = a->tp->is_cl_obj();
1394: //error('d',"dargs %t",a->tp);
1395: if (cln && Pclass(cln->tp)->has_itor()) // mark X(X&) arguments
1396: a->n_xref = 1;
1397: else {
1398: Ptype t = a->tp;
1399: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
1400: if (t->base == FCT) a->tp = new ptr(PTR,a->tp);
1401: }
1402:
1403: if (init = a->n_initializer) { // default argument
1404: Pptr pt;
1405: if (init == dummy) {
1406: error("emptyIr");
1407: a->n_initializer = 0;
1408: continue;
1409: }
1410: if (cln) {
1411: if (init->base==VALUE) {
1412: switch (init->tp2->base) {
1413: case CLASS:
1414: if (Pclass(init->tp2)!=Pclass(cln->tp)) goto inin2;
1415: break;
1416: default:
1417: Pname n2 = init->tp2->is_cl_obj();
1418: if (n2==0 || Pclass(n2->tp)!=Pclass(cln->tp)) goto inin2;
1419: }
1420:
1421: a->n_initializer = init = 0;
1422: error('s',"K as defaultA");
1423: }
1424: else {
1425: inin2:
1426: if (init->base == ILIST) error("list as AIr");
1427: Pexpr i = init->typ(tbl);
1428: init = class_init(a,a->tp,i,tbl);
1429: if (i!=init && init->base==DEREF) {
1430: error('s',"K needed forAIr");
1431: init = 0;
1432: }
1433: else {
1434: void dosimpl(Pexpr,Pname);
1435: dosimpl(init,cc->nof);
1436: // init->simpl();
1437: init->permanent = 2;
1438: }
1439: a->n_initializer = init;
1440: }
1441: }
1442: else if (pt = a->tp->is_ref()) {
1443: extern ref_initializer;
1444: ref_initializer++;
1445: init = init->typ(tbl);
1446: ref_initializer--;
1447: int tcount = stcount;
1448: init = ref_init(pt,init,tbl);
1449: if (tcount != stcount) {
1450: error('s',"needs temporaryV to evaluateAIr");
1451: init = 0;
1452: }
1453: else {
1454: void dosimpl(Pexpr,Pname);
1455: dosimpl(init,cc->nof);
1456: // init->simpl();
1457: init->permanent = 2;
1458: }
1459: a->n_initializer = init;
1460: }
1461: else {
1462: Pptr p = a->tp->is_ptr();
1463: init = init->typ(tbl);
1464: if (p) init = ptr_init(p,init,tbl);
1465:
1466: if (a->tp->check(init->tp,ARG)) {
1467: int i = can_coerce(a->tp,init->tp);
1468:
1469: switch (i) {
1470: case 1:
1471: if (Ncoerce) {
1472: Pname cn = init->tp->is_cl_obj(); Pname xx = new name(Ncoerce->string);
1473: Pref r = new ref(DOT,init,xx);
1474: init = new expr(G_CALL,r,0);
1475: init = init->typ(tbl);
1476: }
1477: break;
1478: default:
1479: error("%d possible conversions for defaultA",i);
1480: case 0:
1481: error("badIrT%t forA%n",init->tp,a);
1482: DEL(init);
1483: a->n_initializer = init = 0;
1484: }
1485: }
1486:
1487: if (init) {
1488: void dosimpl(Pexpr,Pname);
1489: dosimpl(init,cc->nof);
1490: // init->simpl();
1491: init->permanent = 2;
1492: a->n_initializer = init;
1493: Neval = 0;
1494: long i = init->eval();
1495: if (Neval == 0) {
1496: a->n_evaluated = 1;
1497: a->n_val = i;
1498: }
1499: }
1500: }
1501: }
1502: }
1503: const_save = oo;
1504: }
1505:
1506: void merge_init(Pname nn, Pfct f, Pfct nf)
1507: {
1508: // Pname a1 = f->f_args; if (a1==0) a1 = f->argtype;
1509: // Pname a2 = nf->f_args;//nf->argtype;
1510: Pname a1 = f->argtype;
1511: Pname a2 = nf->argtype;
1512:
1513: for (; a1; a1=a1->n_list, a2=a2->n_list) {
1514: int i1 = a1->n_initializer || a1->n_evaluated;
1515: int i2 = a2->n_initializer || a2->n_evaluated;
1516:
1517: if (i1 && i2) error(&a1->where,"twoIrs for%nA%n",nn,a1);
1518:
1519: if (i1) {
1520: a2->n_initializer = a1->n_initializer;
1521: a2->n_evaluated = a1->n_evaluated;
1522: a2->n_val = a1->n_val;
1523: }
1524: if (i2) {
1525: a1->n_initializer = a2->n_initializer;
1526: a1->n_evaluated = a2->n_evaluated;
1527: a1->n_val = a2->n_val;
1528: }
1529:
1530: }
1531: }
1532:
1533: Pexpr try_to_coerce(Ptype rt, Pexpr e, char* s, Ptable tbl)
1534: /*
1535: ``e'' is of class ``cn'' coerce it to type ``rt''
1536: */
1537: {
1538: int i;
1539: Pname cn;
1540: //error('d',"try_to_coerce(%t, %t, %s, %d)",rt,e->tp,s,tbl);
1541:
1542: if ((cn=e->tp->is_cl_obj()) && (i=can_coerce(rt,e->tp)) && Ncoerce) {
1543: if (1 < i) error("%d possible conversions for %s",i,s);
1544: //error('d',"coerce %n",Ncoerce);
1545: Pclass cl = Pclass(cn->tp);
1546: // Pref r = new ref(DOT,e,Ncoerce);
1547: // Pexpr rr = r->typ(tbl);
1548: // Pexpr c = new expr(G_CALL,rr,0);
1549: // c->fct_name = Ncoerce;
1550: Pname xx = new name(Ncoerce->string);
1551: Pref r = new ref(DOT,e,xx);
1552: Pexpr c = new expr(G_CALL,r,0);
1553: // return c->typ(tbl);
1554: c = c->typ(tbl);
1555: //error('d',"coerce -> %k %t",c->base,c->tp);
1556:
1557: return c;
1558: }
1559: //error('d',"coerce ->0");
1560: return 0;
1561: }
1562:
1563: int in_class_dcl;
1564:
1565: Pname name::dofct(Ptable tbl, TOK scope)
1566: {
1567: Pfct f = Pfct(tp);
1568: Pname class_name;
1569: Ptable etbl;
1570: in_class_dcl = cc->not!=0;
1571: int just_made = 0;
1572: // int fvirt = 0; //BSopt
1573: //error('d',"dofct %n %d %t %s",this,tp,tp,tbl==gtbl?"global":"");
1574:
1575: if (f->f_inline) n_sto = STATIC;
1576:
1577: if (n_stclass)
1578: switch (n_stclass) {
1579: case EXTERN:
1580: case STATIC:
1581: case OVERLOAD:
1582: break;
1583: default:
1584: error("%n declared%k",this,n_stclass);
1585: n_stclass = EXTERN;
1586: }
1587:
1588: tp->dcl(tbl); // must be done before the type check
1589:
1590: if (n_qualifier) { // qualified name: c::f() checked above
1591: // ineffective
1592: // if (in_class_dcl) {
1593: // error("unexpectedQdN%n",this);
1594: // return 0;
1595: // }
1596:
1597: if (f->f_virtual) {
1598: error("virtual outsideCD (ignored)");
1599: f->f_virtual = 0;
1600: }
1601:
1602: if (n_sto
1603: && n_sto!=FRIEND // friend X::f();
1604: && f->f_inline==0) { // inline causes n_sto==STATIC
1605: error("%k specifed for QdN%n",n_sto,this);
1606: n_sto = 0;
1607: }
1608:
1609: class_name = Pbase(n_qualifier->tp)->b_name;
1610: etbl = Pclass(class_name->tp)->memtbl;
1611: }
1612: else {
1613: class_name = cc->not;
1614: // beware of local function declarations in member functions
1615: if (class_name && tbl!=cc->cot->memtbl) {
1616: class_name = 0;
1617: in_class_dcl = 0;
1618: }
1619:
1620: if (f->f_static && f->f_virtual) {
1621: error("virtual staticM");
1622: f->f_virtual = 0;
1623: }
1624:
1625: if (n_oper) check_oper(class_name);
1626: etbl = tbl;
1627: }
1628:
1629: // Pfct(tp)->memof = class_name ? Pclass(class_name->tp) : 0;
1630:
1631: Pname find_virtual(Pclass,Pname);
1632:
1633: if (class_name) {
1634: f->memof = Pclass(class_name->tp);
1635: if (f->f_virtual==0 && find_virtual(f->memof,this))
1636: f->f_virtual = VTOK;
1637: }
1638:
1639: if (etbl==0 || etbl->base!=TABLE) error('i',"N::dcl: etbl=%d",etbl);
1640:
1641: switch (n_oper) {
1642: case CTOR:
1643: if (f->f_virtual) {
1644: error("virtualK");
1645: f->f_virtual = 0;
1646: }
1647:
1648: // case DTOR:
1649: // f->f_const = 1;
1650: break;
1651:
1652: case REF:
1653: if (f->argtype)
1654: error("%n takes no argument",this);
1655: else if (f->returns->is_ptr() == 0) {
1656: Pname cn = f->returns->is_cl_obj();
1657: if (cn==0 && f->returns->base==RPTR) cn = Pptr(f->returns)->typ->is_cl_obj();
1658: if (cn==0 || Pclass(cn->tp)->has_oper(REF)==0)
1659: error("%n must return aP toCO, aR toCO, or aCO",this);
1660: }
1661: break;
1662:
1663: case NEW: // void* operator new(long)
1664: if (f->f_virtual)
1665: error("virtual%n (operator new() is static)",this);
1666: if (class_name) f->f_static = 1; // if member: static by default
1667: if (f->nargs_known != 1)
1668: error("ATs must be fully specified for%n",this);
1669: else if (f->nargs<1)
1670: error("%n requires a firstA ofT size_t",this);
1671: else if (f->argtype->tp->check(size_t_type,0)) {
1672: if (strict_opt==0
1673: && f->argtype->tp->check(long_type,0)==0) {
1674: error('w',"%n firstA should be size_t",this);
1675: f->argtype->tp = size_t_type;
1676: if (f->f_signature) f->sign();
1677: }
1678: else
1679: error("%n requires a firstA ofT size_t",this);
1680: }
1681: else {
1682: Ptype t = f->s_returns ? f->s_returns : f->returns;
1683: if (t->check(Pvoid_type,0)) error("bad returnT for %n",this);
1684: }
1685: break;
1686:
1687: case DELETE: // void operator delete(void*) or
1688: // void operator delete(void*, long)
1689: if (f->f_virtual)
1690: error("virtual%n (operator delete() is static)",this);
1691: if (class_name) f->f_static = 1; // if member: static by default
1692: if (f->nargs_known != 1)
1693: error("ATs must be fully specified for%n",this);
1694: else {
1695: Ptype t = f->s_returns ? f->s_returns : f->returns;
1696: if (t->base != VOID)
1697: error("bad returnT for %n", this);
1698: else {
1699: switch (f->nargs) {
1700: default:
1701: error("%n takes 1 or 2As",this);
1702: break;
1703: case 1:
1704: case 2:
1705: { Pname a = f->argtype;
1706: if (a->tp->check(Pvoid_type,0))
1707: error("%n's 1stA must be a void*",this);
1708: else if (a = a->n_list) {
1709: if (class_name == 0)
1710: error("%n takes only oneA",this);
1711: else if (a->tp->check(size_t_type,0)) {
1712: if (strict_opt==0
1713: && a->tp->check(long_type,0)==0) {
1714: error('w',"%n's 2ndA should be a size_t",this);
1715: a->tp = size_t_type;
1716: if (f->f_signature) f->sign();
1717: }
1718: else
1719: error("%n's 2ndA must be a size_t",this);
1720: }
1721: }
1722: }
1723: }
1724: }
1725: }
1726: break;
1727:
1728: case ASSIGN:
1729: if (class_name && f->nargs==1) {
1730: Ptype t = f->argtype->tp;
1731: Pname an = t->is_cl_obj(); // X::operator=(X) ?
1732: if (an==0 && (t=t->is_ref())) { // X::operator=(X&) ?
1733: t = Pptr(t)->typ;
1734: rx1:
1735: switch (t->base) {
1736: case TYPE: t = Pbase(t)->b_name->tp; goto rx1;
1737: case COBJ: an = Pbase(t)->b_name;
1738: }
1739: }
1740: if (an && an==class_name) Pclass(an->tp)->c_xref |= C_ASS;
1741: }
1742: else if (f->nargs == 2) {
1743: Ptype t = f->argtype->tp;
1744: Pname an1;
1745: if (t=t->is_ref()) { // operator=(X&,?) ?
1746: t = Pptr(t)->typ;
1747: rx2:
1748: switch (t->base) {
1749: case TYPE: t = Pbase(t)->b_name->tp; goto rx2;
1750: case COBJ: an1 = Pbase(t)->b_name;
1751: }
1752: }
1753: t = f->argtype->n_list->tp;
1754: Pname an2 = t->is_cl_obj(); // operator=(X&,X) ?
1755: if (an2==0 && (t=t->is_ref())) { // operator=(X&,X&) ?
1756: t = Pptr(t)->typ;
1757: rx3:
1758: switch (t->base) {
1759: case TYPE: t = Pbase(t)->b_name->tp; goto rx3;
1760: case COBJ: an2 = Pbase(t)->b_name;
1761: }
1762: }
1763: if (an1 && an1==an2) Pclass(an1->tp)->c_xref |= C_ASS;
1764: }
1765: }
1766:
1767: switch (scope) {
1768: case FCT:
1769: case ARG:
1770: if (n_sto == STATIC) error("D of staticF in aF");
1771: }
1772:
1773: Pname nn = etbl->insert(this,0);
1774: nn->assign();
1775: n_table = etbl;
1776: //error('d',"nn %n %t %d %d",nn,nn->tp,nn->tp,f);
1777:
1778: if (n_initializer) {
1779: if (f->f_virtual == 0) error("Ir for non-virtualF%n",this);
1780: if (n_initializer != zero) error("virtualFIr must be 0");
1781: }
1782:
1783: if (Nold) {
1784: Pfct nf = Pfct(nn->tp);
1785: //error('d',"old %n: %t and %t",nn,nf,tp);
1786: if (nf->base==ANY || f->base==ANY)
1787: ;
1788: else if (nf->base == OVERLOAD) {
1789: string = nn->string;
1790: nn = Pgen(nf)->add(this);
1791:
1792: if (Nold == 0) {
1793: if (f->body && n_qualifier) {
1794: error("badAL for %n::%s()",n_qualifier,string);
1795: return 0;
1796: }
1797: goto thth;
1798: }
1799: // else {
1800: // if (f->body==0 && friend_in_class==0) error('w',"%n redeclared",nn);
1801: // }
1802:
1803: nf = Pfct(nn->tp);
1804:
1805: if (nf->body && f->body) {
1806: // Preserve the original definition in the case of a
1807: // PT class, it is the one that was supplied by the user
1808: if (!(class_name &&
1809: (Pclass(class_name->tp)->class_base ==
1810: instantiated_template_class) && nn->n_redefined))
1811: {
1812: error("two definitions of%n",this);
1813: f->body = 0;
1814: }
1815: return 0;
1816: }
1817:
1818: if (f->body) goto bdbd;
1819:
1820: goto stst;
1821: }
1822: else if (nf->base != FCT) {
1823: error("%n declared both as%t and asF",this,nf);
1824: f->body = 0;
1825: }
1826: else {
1827: //error('d',"%t->check(%t) -> %d %d",nf,f,nf->check(f,OVERLOAD)/*,vrp_equiv*/);
1828: if (nf->check(f,OVERLOAD)/* || vrp_equiv */|| const_problem) {
1829: if (f->body && n_qualifier) {
1830: error("%nT mismatch: %t and %t",nn,nf,f);
1831: return 0;
1832: }
1833: Pgen g = new gen;
1834: add_first = 1;
1835: Pname n1 = g->add(nn);
1836: add_first = 0;
1837: string = nn->string;
1838: Pname n2 = g->add(this);
1839: nn->tp = g;
1840: nn = n2;
1841: goto thth;
1842: }
1843:
1844: if (in_class_dcl) {
1845: // error("twoDs of%n",this);
1846: // f->body = 0;
1847: // return 0;
1848: }
1849: else if (nf->f_static && f->f_inline==0 && n_sto==STATIC) {
1850: //error('d',"MF%n declared static outsideF",this);
1851: n_sto = 0;
1852: }
1853: else if (n_sto && n_sto!=nn->n_scope) {
1854: if (n_sto==EXTERN && nn->n_scope==STATIC)
1855: error('w',"%n declared extern after being declared static",this);
1856: else if (nf->f_inline==0 && f->f_inline==0) {
1857: extern Pname new_fct; // beware of pre-defined functions
1858: extern Pname del_fct;
1859: if (nn->tp==new_fct->tp || nn->tp==del_fct->tp)
1860: nn->n_sto = n_sto;
1861: else
1862: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:EXTERN);
1863: }
1864: }
1865:
1866: //error('d',"fct %n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope);
1867:
1868: extern linkage;
1869: //error('d',"link %d lcount %d sig %s",linkage,lcount,nf->f_signature);
1870: if (linkage && nf->f_signature && nf->f_signature[0])
1871: error("inconsistent linkage specifications for%n",this);
1872: if (nf->body && f->body) {
1873: // Preserve the original definition in the case of a
1874: // PT class, it is the one that was supplied by the user
1875: if (!(class_name &&
1876: (Pclass(class_name->tp)->class_base ==
1877: instantiated_template_class) && nn->n_redefined))
1878: {
1879: error("two definitions of%n",this);
1880: f->body = 0;
1881: }
1882: return 0;
1883: }
1884:
1885: if (f->body) goto bdbd;
1886:
1887: goto stst;
1888:
1889: bdbd:
1890: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
1891: f->f_virtual = nf->f_virtual;
1892: f->f_this = nf->f_this;
1893: f->f_result = nf->f_result;
1894: f->s_returns = nf->s_returns;
1895: f->f_args = nf->f_args;
1896: // f->argtype = nf->argtype;
1897: f->f_signature = nf->f_signature;
1898: f->f_const = nf->f_const;
1899: f->f_static = nf->f_static;
1900: nn->tp = f;
1901: if (f->f_inline) {
1902: if (nf->f_inline==0) {
1903: if (nn->n_used && nn->n_sto!=STATIC)
1904: error("%n declared with external linkage and called before defined as inline",nn);
1905: // else if (nf->memof)
1906: // error('w',"%n declared as non-inline but defined as inline",nn);
1907: else if (nn->n_used) {
1908: nn->take_addr(); // force printout
1909: if (warning_opt) error('w',"%n called before defined as inline",nn);
1910: }
1911: }
1912: nf->f_inline = 1;
1913: nn->n_sto = STATIC;
1914: }
1915: else if (nf->f_inline) {
1916: // error('w',"%n defined as inline but not declared as inline",this);
1917: f->f_inline = 1;
1918: }
1919: goto stst2;
1920:
1921: stst:
1922: //error('d',"stst");
1923: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
1924: f->f_args = nf->f_args;
1925: // f->argtype = nf->argtype;
1926: stst2:
1927: //error('d',"stst2 %n printed %d",nn,nn->n_dcl_printed);
1928: if (f->f_inline) n_sto = STATIC;
1929: if (n_sto
1930: && nn->n_scope!=n_sto
1931: && friend_in_class==0
1932: && f->f_inline==0){ // allow re-def to "static"
1933: if (n_sto == STATIC)
1934: nn->n_sto = STATIC;
1935: else {
1936: error("%n both%k and%k",this,n_sto,nn->n_scope);
1937: }
1938: }
1939: n_scope = nn->n_scope; // first specifier wins
1940: n_sto = nn->n_sto;
1941: }
1942: }
1943: else { // new function: make f_this for member functions
1944: thth:
1945: just_made = 1;
1946: if (f->f_inline)
1947: nn->n_sto = STATIC;
1948: else if (class_name==0 && n_sto==0 && f->body==0)
1949: nn->n_sto = EXTERN;
1950: //error('d',"thth %n %t static %d sto %k",nn,f,f->f_static,nn->n_sto);
1951: if (f->f_static)
1952: switch (n_oper) { // what about + ??
1953: case CTOR:
1954: case DTOR:
1955: case TYPE:
1956: case CALL:
1957: case DEREF:
1958: case REF:
1959: error("%n cannot be a staticMF",nn);
1960: f->f_static = 0;
1961: }
1962:
1963: if (class_name
1964: && f->f_static==0 // no ``this'' in static members
1965: && n_oper!=NEW // X::operator new() static by default
1966: && n_oper!=DELETE // X::operator delete() static by default
1967: && etbl!=gtbl) { /* beware of implicit declatation */
1968: Pname cn = nn->n_table->t_name;
1969: Pname tt = new name("this");
1970: tt->n_scope = ARG;
1971: tt->where = no_where;
1972: // tt->n_sto = ARG;
1973: tt->tp = Pclass(class_name->tp)->this_type;
1974: PERM(tt);
1975: Pfct(nn->tp)->f_this = f->f_this = Pfct(nn->tp)->f_args = f->f_args = tt;
1976: tt->n_list = f->argtype;
1977: //error('d',"nn %n tp %t const %d",nn,nn->tp,f->f_const);
1978: if (f->f_const /*&& n_oper!=CTOR && n_oper!=DTOR*/) {
1979: Pbase x = Pbase(Pptr(tt->tp)->typ);
1980: Pbase y = new basetype(COBJ,0);
1981: *y = *x;
1982: y->b_const = 1;
1983: tt->tp = new ptr(PTR,y);
1984: PERM(tt->tp);
1985: }
1986:
1987: }
1988: else {
1989: Pfct(nn->tp)->f_args = f->f_args = f->f_result?f->f_result:f->argtype;
1990: Pfct(nn->tp)->f_signature = f->f_signature;
1991: Pfct(nn->tp)->f_const = f->f_const;
1992: Pfct(nn->tp)->f_static = f->f_static;
1993: }
1994:
1995: extern linkage;
1996: // if C++ linkage encode type in function name
1997: if (linkage==0 && Pfct(nn->tp)->f_signature==0) Pfct(nn->tp)->sign();
1998:
1999: if (f->f_result == 0) {
2000: //error('d',"re1 %n %t %d",this,f,f);
2001: make_res(f);
2002: }
2003: else if (f->f_this)
2004: f->f_this->n_list = f->f_result;
2005:
2006: if (nn->n_oper==CTOR || nn->n_oper==DTOR) vbase_pointers(nn,Pclass(class_name->tp));
2007:
2008: if (f->f_virtual) {
2009: switch (nn->n_scope) {
2010: default:
2011: error("nonC virtual%n",this);
2012: break;
2013: case 0:
2014: case PUBLIC:
2015: // if (fvirt) //BSopt
2016: cc->cot->virt_count = 1;
2017: Pfct(nn->tp)->f_virtual = f->f_virtual;
2018: break;
2019: }
2020: }
2021: }
2022:
2023: /* an operator must take at least one class object or
2024: reference to class object argument
2025: */
2026:
2027: if (just_made)
2028: switch (n_oper) {
2029: case CTOR:
2030: switch (f->nargs) { // check for X(X) and X(X&)
2031: case 0:
2032: break;
2033: default: // handle X(X&, int i = 0)
2034: { Pname n2 = f->argtype->n_list;
2035: if (n2->n_initializer==0 && n2->n_evaluated==0) break;
2036: }
2037: case 1:
2038: {
2039: Ptype t = f->argtype->tp;
2040: clll:
2041: switch (t->base) {
2042: case TYPE:
2043: t = Pbase(t)->b_name->tp;
2044: goto clll;
2045: case RPTR: /* X(X&) ? */
2046: t = Pptr(t)->typ;
2047: cxll:
2048: switch (t->base) {
2049: case TYPE:
2050: t = Pbase(t)->b_name->tp;
2051: goto cxll;
2052: case COBJ:
2053: if (class_name == Pbase(t)->b_name)
2054: Pclass(class_name->tp)->c_itor = nn;
2055: }
2056: break;
2057: case COBJ: /* X(X) ? */
2058: if (class_name == Pbase(t)->b_name) {
2059: error("badK %s(%s) use %s(%s&)",class_name->string,class_name->string,class_name->string,class_name->string);
2060: f->argtype->tp = any_type;
2061: }
2062: }
2063: }
2064: }
2065: if (Pclass(class_name->tp)->c_ctor == 0) Pclass(class_name->tp)->c_ctor = nn;
2066: break;
2067:
2068: case TYPE:
2069: // somewhat simple minded solution to the inheritance of
2070: // conversion operator problem
2071: nn->n_list = Pclass(class_name->tp)->conv;
2072: Pclass(class_name->tp)->conv = nn;
2073: break;
2074:
2075: case DTOR:
2076: Pclass(class_name->tp)->c_dtor = nn;
2077: break;
2078:
2079: case NEW: // void* operator new(long)
2080: /*
2081: if (Pfct(nn->tp)->f_virtual)
2082: error("virtual%n (operator new() is static)",this);
2083: if (class_name) Pfct(nn->tp)->f_static = f->f_static = 1; // if member: static by default
2084: if (f->nargs_known != 1)
2085: error("ATs must be fully specified for%n",nn);
2086: else if (f->nargs<1)
2087: error("%n requires a firstA ofT size_t", nn);
2088: else if (f->argtype->tp->check(size_t_type,0)) {
2089: if (strict_opt==0
2090: && f->argtype->tp->check(long_type,0)==0) {
2091: error('w',"%n firstA should be size_t",nn);
2092: f->argtype->tp = size_t_type;
2093: if (f->f_signature) Pfct(nn->tp)->sign();
2094: }
2095: else
2096: error("%n requires a firstA ofT size_t",nn);
2097: }
2098: else {
2099: Ptype t = f->s_returns ? f->s_returns : f->returns;
2100: if (t->check(Pvoid_type,0)) error("bad returnT for %n", nn);
2101: }
2102: break;
2103: */
2104: case DELETE: // void operator delete(void*) or
2105: // void operator delete(void*, long)
2106: /*
2107: //error('d',"delete %n %t",nn,nn->tp);
2108: if (Pfct(nn->tp)->f_virtual)
2109: error("virtual%n (operator delete() is static)",this);
2110: if (class_name) Pfct(nn->tp)->f_static = f->f_static = 1; // if member: static by default
2111: if (f->nargs_known != 1)
2112: error("ATs must be fully specified for%n",nn);
2113: else {
2114: Ptype t = f->s_returns ? f->s_returns : f->returns;
2115: if (t->base != VOID)
2116: error("bad returnT for %n", nn);
2117: else {
2118: switch (f->nargs) {
2119: default:
2120: error("%n takes 1 or 2As",nn);
2121: break;
2122: case 1:
2123: case 2:
2124: { Pname a = f->argtype;
2125: if (a->tp->check(Pvoid_type,0))
2126: error("%n's 1stA must be a void*",nn);
2127: else if (a = a->n_list) {
2128: if (class_name == 0)
2129: error("%n takes only oneA",nn);
2130: else if (a->tp->check(size_t_type,0)) {
2131: if (strict_opt==0
2132: && a->tp->check(long_type,0)==0) {
2133: error('w',"%n's 2ndA should be a size_t",nn);
2134: a->tp = size_t_type;
2135: if (f->f_signature) Pfct(nn->tp)->sign();
2136: }
2137: else
2138: error("%n's 2ndA must be a size_t", nn);
2139: }
2140: }
2141: }
2142: }
2143: }
2144: }
2145: break;
2146: */
2147: case CALL:
2148: case 0:
2149: break;
2150:
2151: default:
2152: if (f->nargs_known != 1) {
2153: error("ATs must be fully specified for%n",nn);
2154: }
2155: else if (class_name == 0) {
2156: Pname a;
2157: switch (f->nargs) {
2158: case 1:
2159: case 2:
2160: for (a=f->argtype; a; a=a->n_list) {
2161: Ptype tx = a->tp;
2162: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp;
2163: if (tx->is_ref()) tx = Pptr(tx)->typ;
2164: if (tx->is_cl_obj()) goto cok;
2165: }
2166: error("%n must take at least oneCTA",nn);
2167: break;
2168: default:
2169: error("%n must take 1 or 2As",nn);
2170: }
2171: }
2172: else {
2173: switch (f->nargs) {
2174: case 0:
2175: case 1:
2176: break;
2177: default:
2178: error("%n must take 0 or 1As",nn);
2179: }
2180: }
2181: cok:;
2182: }
2183:
2184: int i = 0; // check that every argument after an argument with
2185: // initializer have an initializer
2186: for (Pname a = f->f_args/*f->argtype*/; a; a=a->n_list) {
2187: if (a->n_initializer)
2188: i = 1;
2189: else if (i)
2190: error("trailingA%n withoutIr",a);
2191: }
2192:
2193: /*
2194: the body cannot be checked until the name
2195: has been checked and entered into its table
2196: */
2197: if (f->body) f->dcl(nn);
2198: return nn;
2199: }
2200: /* ODI notes -
2201: template classes
2202: n_gen_fct_name -- this used to be an invalid pun on
2203: another field.
2204: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.